diff options
Diffstat (limited to 'system/easy-kernel/0100-linux-6.1.3.patch')
-rw-r--r-- | system/easy-kernel/0100-linux-6.1.3.patch | 49142 |
1 files changed, 49142 insertions, 0 deletions
diff --git a/system/easy-kernel/0100-linux-6.1.3.patch b/system/easy-kernel/0100-linux-6.1.3.patch new file mode 100644 index 000000000..c85462c45 --- /dev/null +++ b/system/easy-kernel/0100-linux-6.1.3.patch @@ -0,0 +1,49142 @@ +diff --git a/Documentation/ABI/stable/sysfs-driver-dma-idxd b/Documentation/ABI/stable/sysfs-driver-dma-idxd +index 8e2c2c405db22..3becc9a82bdf6 100644 +--- a/Documentation/ABI/stable/sysfs-driver-dma-idxd ++++ b/Documentation/ABI/stable/sysfs-driver-dma-idxd +@@ -22,6 +22,7 @@ Date: Oct 25, 2019 + KernelVersion: 5.6.0 + Contact: dmaengine@vger.kernel.org + Description: The largest number of work descriptors in a batch. ++ It's not visible when the device does not support batch. + + What: /sys/bus/dsa/devices/dsa<m>/max_work_queues_size + Date: Oct 25, 2019 +@@ -49,6 +50,8 @@ Description: The total number of read buffers supported by this device. + The read buffers represent resources within the DSA + implementation, and these resources are allocated by engines to + support operations. See DSA spec v1.2 9.2.4 Total Read Buffers. ++ It's not visible when the device does not support Read Buffer ++ allocation control. + + What: /sys/bus/dsa/devices/dsa<m>/max_transfer_size + Date: Oct 25, 2019 +@@ -122,6 +125,8 @@ Contact: dmaengine@vger.kernel.org + Description: The maximum number of read buffers that may be in use at + one time by operations that access low bandwidth memory in the + device. See DSA spec v1.2 9.2.8 GENCFG on Global Read Buffer Limit. ++ It's not visible when the device does not support Read Buffer ++ allocation control. + + What: /sys/bus/dsa/devices/dsa<m>/cmd_status + Date: Aug 28, 2020 +@@ -205,6 +210,7 @@ KernelVersion: 5.10.0 + Contact: dmaengine@vger.kernel.org + Description: The max batch size for this workqueue. Cannot exceed device + max batch size. Configurable parameter. ++ It's not visible when the device does not support batch. + + What: /sys/bus/dsa/devices/wq<m>.<n>/ats_disable + Date: Nov 13, 2020 +@@ -250,6 +256,8 @@ KernelVersion: 5.17.0 + Contact: dmaengine@vger.kernel.org + Description: Enable the use of global read buffer limit for the group. See DSA + spec v1.2 9.2.18 GRPCFG Use Global Read Buffer Limit. ++ It's not visible when the device does not support Read Buffer ++ allocation control. + + What: /sys/bus/dsa/devices/group<m>.<n>/read_buffers_allowed + Date: Dec 10, 2021 +@@ -258,6 +266,8 @@ Contact: dmaengine@vger.kernel.org + Description: Indicates max number of read buffers that may be in use at one time + by all engines in the group. See DSA spec v1.2 9.2.18 GRPCFG Read + Buffers Allowed. ++ It's not visible when the device does not support Read Buffer ++ allocation control. + + What: /sys/bus/dsa/devices/group<m>.<n>/read_buffers_reserved + Date: Dec 10, 2021 +@@ -266,6 +276,8 @@ Contact: dmaengine@vger.kernel.org + Description: Indicates the number of Read Buffers reserved for the use of + engines in the group. See DSA spec v1.2 9.2.18 GRPCFG Read Buffers + Reserved. ++ It's not visible when the device does not support Read Buffer ++ allocation control. + + What: /sys/bus/dsa/devices/group<m>.<n>/desc_progress_limit + Date: Sept 14, 2022 +diff --git a/Documentation/ABI/testing/sysfs-bus-spi-devices-spi-nor b/Documentation/ABI/testing/sysfs-bus-spi-devices-spi-nor +index d76cd3946434d..e9ef69aef20b1 100644 +--- a/Documentation/ABI/testing/sysfs-bus-spi-devices-spi-nor ++++ b/Documentation/ABI/testing/sysfs-bus-spi-devices-spi-nor +@@ -5,6 +5,9 @@ Contact: linux-mtd@lists.infradead.org + Description: (RO) The JEDEC ID of the SPI NOR flash as reported by the + flash device. + ++ The attribute is not present if the flash doesn't support ++ the "Read JEDEC ID" command (9Fh). This is the case for ++ non-JEDEC compliant flashes. + + What: /sys/bus/spi/devices/.../spi-nor/manufacturer + Date: April 2021 +diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst +index 98d1b198b2b4c..c2c64c1b706ff 100644 +--- a/Documentation/admin-guide/sysctl/kernel.rst ++++ b/Documentation/admin-guide/sysctl/kernel.rst +@@ -1314,6 +1314,29 @@ watchdog work to be queued by the watchdog timer function, otherwise the NMI + watchdog — if enabled — can detect a hard lockup condition. + + ++split_lock_mitigate (x86 only) ++============================== ++ ++On x86, each "split lock" imposes a system-wide performance penalty. On larger ++systems, large numbers of split locks from unprivileged users can result in ++denials of service to well-behaved and potentially more important users. ++ ++The kernel mitigates these bad users by detecting split locks and imposing ++penalties: forcing them to wait and only allowing one core to execute split ++locks at a time. ++ ++These mitigations can make those bad applications unbearably slow. Setting ++split_lock_mitigate=0 may restore some application performance, but will also ++increase system exposure to denial of service attacks from split lock users. ++ ++= =================================================================== ++0 Disable the mitigation mode - just warns the split lock on kernel log ++ and exposes the system to denials of service from the split lockers. ++1 Enable the mitigation mode (this is the default) - penalizes the split ++ lockers with intentional performance degradation. ++= =================================================================== ++ ++ + stack_erasing + ============= + +diff --git a/Documentation/devicetree/bindings/input/azoteq,iqs7222.yaml b/Documentation/devicetree/bindings/input/azoteq,iqs7222.yaml +index 02e605fac408d..9ddba7f2e7aa6 100644 +--- a/Documentation/devicetree/bindings/input/azoteq,iqs7222.yaml ++++ b/Documentation/devicetree/bindings/input/azoteq,iqs7222.yaml +@@ -473,9 +473,6 @@ patternProperties: + Specifies whether the event is to be interpreted as a key (1) + or a switch (5). + +- required: +- - linux,code +- + additionalProperties: false + + dependencies: +@@ -501,7 +498,7 @@ patternProperties: + + azoteq,slider-size: + $ref: /schemas/types.yaml#/definitions/uint32 +- minimum: 0 ++ minimum: 1 + maximum: 65535 + description: + Specifies the slider's one-dimensional resolution, equal to the +@@ -575,9 +572,9 @@ patternProperties: + linux,code: true + + azoteq,gesture-max-ms: +- multipleOf: 4 ++ multipleOf: 16 + minimum: 0 +- maximum: 1020 ++ maximum: 4080 + description: + Specifies the length of time (in ms) within which a tap, swipe + or flick gesture must be completed in order to be acknowledged +@@ -585,9 +582,9 @@ patternProperties: + gesture applies to all remaining swipe or flick gestures. + + azoteq,gesture-min-ms: +- multipleOf: 4 ++ multipleOf: 16 + minimum: 0 +- maximum: 124 ++ maximum: 496 + description: + Specifies the length of time (in ms) for which a tap gesture must + be held in order to be acknowledged by the device. +@@ -620,9 +617,6 @@ patternProperties: + GPIO, they must all be of the same type (proximity, touch or + slider gesture). + +- required: +- - linux,code +- + additionalProperties: false + + required: +@@ -693,6 +687,7 @@ allOf: + properties: + azoteq,slider-size: + multipleOf: 16 ++ minimum: 16 + maximum: 4080 + + azoteq,top-speed: +@@ -935,14 +930,14 @@ examples: + + event-tap { + linux,code = <KEY_PLAYPAUSE>; +- azoteq,gesture-max-ms = <600>; +- azoteq,gesture-min-ms = <24>; ++ azoteq,gesture-max-ms = <400>; ++ azoteq,gesture-min-ms = <32>; + }; + + event-flick-pos { + linux,code = <KEY_NEXTSONG>; +- azoteq,gesture-max-ms = <600>; +- azoteq,gesture-dist = <816>; ++ azoteq,gesture-max-ms = <800>; ++ azoteq,gesture-dist = <800>; + }; + + event-flick-neg { +diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml +index 6a3e3ede1ede7..777f2da52f1ed 100644 +--- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml ++++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml +@@ -98,6 +98,10 @@ properties: + type: object + $ref: /schemas/regulator/qcom,spmi-regulator.yaml# + ++ pwm: ++ type: object ++ $ref: /schemas/leds/leds-qcom-lpg.yaml# ++ + patternProperties: + "^adc@[0-9a-f]+$": + type: object +@@ -123,10 +127,6 @@ patternProperties: + type: object + $ref: /schemas/power/reset/qcom,pon.yaml# + +- "pwm@[0-9a-f]+$": +- type: object +- $ref: /schemas/leds/leds-qcom-lpg.yaml# +- + "^rtc@[0-9a-f]+$": + type: object + $ref: /schemas/rtc/qcom-pm8xxx-rtc.yaml# +diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml +index 376e739bcad40..49b4f7a32e71e 100644 +--- a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml ++++ b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml +@@ -14,9 +14,6 @@ description: |+ + This PCIe host controller is based on the Synopsys DesignWare PCIe IP + and thus inherits all the common properties defined in snps,dw-pcie.yaml. + +-allOf: +- - $ref: /schemas/pci/snps,dw-pcie.yaml# +- + properties: + compatible: + enum: +@@ -61,7 +58,7 @@ properties: + - const: pcie + - const: pcie_bus + - const: pcie_phy +- - const: pcie_inbound_axi for imx6sx-pcie, pcie_aux for imx8mq-pcie ++ - enum: [ pcie_inbound_axi, pcie_aux ] + + num-lanes: + const: 1 +@@ -175,6 +172,47 @@ required: + - clocks + - clock-names + ++allOf: ++ - $ref: /schemas/pci/snps,dw-pcie.yaml# ++ - if: ++ properties: ++ compatible: ++ contains: ++ const: fsl,imx6sx-pcie ++ then: ++ properties: ++ clock-names: ++ items: ++ - {} ++ - {} ++ - {} ++ - const: pcie_inbound_axi ++ - if: ++ properties: ++ compatible: ++ contains: ++ const: fsl,imx8mq-pcie ++ then: ++ properties: ++ clock-names: ++ items: ++ - {} ++ - {} ++ - {} ++ - const: pcie_aux ++ - if: ++ properties: ++ compatible: ++ not: ++ contains: ++ enum: ++ - fsl,imx6sx-pcie ++ - fsl,imx8mq-pcie ++ then: ++ properties: ++ clock-names: ++ maxItems: 3 ++ + unevaluatedProperties: false + + examples: +diff --git a/Documentation/devicetree/bindings/pci/toshiba,visconti-pcie.yaml b/Documentation/devicetree/bindings/pci/toshiba,visconti-pcie.yaml +index 48ed227fc5b9e..53da2edd7c9ab 100644 +--- a/Documentation/devicetree/bindings/pci/toshiba,visconti-pcie.yaml ++++ b/Documentation/devicetree/bindings/pci/toshiba,visconti-pcie.yaml +@@ -36,7 +36,7 @@ properties: + - const: mpu + + interrupts: +- maxItems: 1 ++ maxItems: 2 + + clocks: + items: +@@ -94,8 +94,9 @@ examples: + #interrupt-cells = <1>; + ranges = <0x81000000 0 0x40000000 0 0x40000000 0 0x00010000>, + <0x82000000 0 0x50000000 0 0x50000000 0 0x20000000>; +- interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>; +- interrupt-names = "intr"; ++ interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>; ++ interrupt-names = "msi", "intr"; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = + <0 0 0 1 &gic GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH +diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt7986-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt7986-pinctrl.yaml +index 89b8f3dd67a19..3342847dcb19a 100644 +--- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt7986-pinctrl.yaml ++++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt7986-pinctrl.yaml +@@ -87,6 +87,8 @@ patternProperties: + "wifi_led" "led" 1, 2 + "i2c" "i2c" 3, 4 + "uart1_0" "uart" 7, 8, 9, 10 ++ "uart1_rx_tx" "uart" 42, 43 ++ "uart1_cts_rts" "uart" 44, 45 + "pcie_clk" "pcie" 9 + "pcie_wake" "pcie" 10 + "spi1_0" "spi" 11, 12, 13, 14 +@@ -98,9 +100,11 @@ patternProperties: + "emmc_45" "emmc" 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32 + "spi1_1" "spi" 23, 24, 25, 26 +- "uart1_2" "uart" 29, 30, 31, 32 ++ "uart1_2_rx_tx" "uart" 29, 30 ++ "uart1_2_cts_rts" "uart" 31, 32 + "uart1_1" "uart" 23, 24, 25, 26 +- "uart2_0" "uart" 29, 30, 31, 32 ++ "uart2_0_rx_tx" "uart" 29, 30 ++ "uart2_0_cts_rts" "uart" 31, 32 + "spi0" "spi" 33, 34, 35, 36 + "spi0_wp_hold" "spi" 37, 38 + "uart1_3_rx_tx" "uart" 35, 36 +@@ -157,7 +161,7 @@ patternProperties: + then: + properties: + groups: +- enum: [emmc, emmc_rst] ++ enum: [emmc_45, emmc_51] + - if: + properties: + function: +@@ -221,8 +225,12 @@ patternProperties: + then: + properties: + groups: +- enum: [uart1_0, uart1_1, uart1_2, uart1_3_rx_tx, +- uart1_3_cts_rts, uart2_0, uart2_1, uart0, uart1, uart2] ++ items: ++ enum: [uart1_0, uart1_rx_tx, uart1_cts_rts, uart1_1, ++ uart1_2_rx_tx, uart1_2_cts_rts, uart1_3_rx_tx, ++ uart1_3_cts_rts, uart2_0_rx_tx, uart2_0_cts_rts, ++ uart2_1, uart0, uart1, uart2] ++ maxItems: 2 + - if: + properties: + function: +@@ -356,6 +364,27 @@ examples: + interrupt-parent = <&gic>; + #interrupt-cells = <2>; + ++ pcie_pins: pcie-pins { ++ mux { ++ function = "pcie"; ++ groups = "pcie_clk", "pcie_wake", "pcie_pereset"; ++ }; ++ }; ++ ++ pwm_pins: pwm-pins { ++ mux { ++ function = "pwm"; ++ groups = "pwm0", "pwm1_0"; ++ }; ++ }; ++ ++ spi0_pins: spi0-pins { ++ mux { ++ function = "spi"; ++ groups = "spi0", "spi0_wp_hold"; ++ }; ++ }; ++ + uart1_pins: uart1-pins { + mux { + function = "uart"; +@@ -363,6 +392,13 @@ examples: + }; + }; + ++ uart1_3_pins: uart1-3-pins { ++ mux { ++ function = "uart"; ++ groups = "uart1_3_rx_tx", "uart1_3_cts_rts"; ++ }; ++ }; ++ + uart2_pins: uart2-pins { + mux { + function = "uart"; +diff --git a/Documentation/devicetree/bindings/pwm/microchip,corepwm.yaml b/Documentation/devicetree/bindings/pwm/microchip,corepwm.yaml +index a7fae1772a81b..cd8e9a8907f84 100644 +--- a/Documentation/devicetree/bindings/pwm/microchip,corepwm.yaml ++++ b/Documentation/devicetree/bindings/pwm/microchip,corepwm.yaml +@@ -30,7 +30,9 @@ properties: + maxItems: 1 + + "#pwm-cells": +- const: 2 ++ enum: [2, 3] ++ description: ++ The only flag supported by the controller is PWM_POLARITY_INVERTED. + + microchip,sync-update-mask: + description: | +diff --git a/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt b/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt +index 5d6ea66a863fe..1f75feec3dec6 100644 +--- a/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt ++++ b/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt +@@ -109,7 +109,7 @@ audio-codec@1{ + reg = <1 0>; + interrupts = <&msmgpio 54 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "intr2" +- reset-gpios = <&msmgpio 64 0>; ++ reset-gpios = <&msmgpio 64 GPIO_ACTIVE_LOW>; + slim-ifc-dev = <&wc9335_ifd>; + clock-names = "mclk", "native"; + clocks = <&rpmcc RPM_SMD_DIV_CLK1>, +diff --git a/Documentation/devicetree/bindings/sound/rt5682.txt b/Documentation/devicetree/bindings/sound/rt5682.txt +index c5f2b8febceec..6b87db68337c2 100644 +--- a/Documentation/devicetree/bindings/sound/rt5682.txt ++++ b/Documentation/devicetree/bindings/sound/rt5682.txt +@@ -46,7 +46,7 @@ Optional properties: + + - realtek,dmic-clk-driving-high : Set the high driving of the DMIC clock out. + +-- #sound-dai-cells: Should be set to '<0>'. ++- #sound-dai-cells: Should be set to '<1>'. + + Pins on the device (for linking into audio routes) for RT5682: + +diff --git a/Documentation/driver-api/spi.rst b/Documentation/driver-api/spi.rst +index f64cb666498aa..f28887045049d 100644 +--- a/Documentation/driver-api/spi.rst ++++ b/Documentation/driver-api/spi.rst +@@ -25,8 +25,8 @@ hardware, which may be as simple as a set of GPIO pins or as complex as + a pair of FIFOs connected to dual DMA engines on the other side of the + SPI shift register (maximizing throughput). Such drivers bridge between + whatever bus they sit on (often the platform bus) and SPI, and expose +-the SPI side of their device as a :c:type:`struct spi_master +-<spi_master>`. SPI devices are children of that master, ++the SPI side of their device as a :c:type:`struct spi_controller ++<spi_controller>`. SPI devices are children of that master, + represented as a :c:type:`struct spi_device <spi_device>` and + manufactured from :c:type:`struct spi_board_info + <spi_board_info>` descriptors which are usually provided by +diff --git a/Documentation/fault-injection/fault-injection.rst b/Documentation/fault-injection/fault-injection.rst +index 17779a2772e51..5f6454b9dbd4d 100644 +--- a/Documentation/fault-injection/fault-injection.rst ++++ b/Documentation/fault-injection/fault-injection.rst +@@ -83,9 +83,7 @@ configuration of fault-injection capabilities. + - /sys/kernel/debug/fail*/times: + + specifies how many times failures may happen at most. A value of -1 +- means "no limit". Note, though, that this file only accepts unsigned +- values. So, if you want to specify -1, you better use 'printf' instead +- of 'echo', e.g.: $ printf %#x -1 > times ++ means "no limit". + + - /sys/kernel/debug/fail*/space: + +@@ -284,7 +282,7 @@ Application Examples + echo Y > /sys/kernel/debug/$FAILTYPE/task-filter + echo 10 > /sys/kernel/debug/$FAILTYPE/probability + echo 100 > /sys/kernel/debug/$FAILTYPE/interval +- printf %#x -1 > /sys/kernel/debug/$FAILTYPE/times ++ echo -1 > /sys/kernel/debug/$FAILTYPE/times + echo 0 > /sys/kernel/debug/$FAILTYPE/space + echo 2 > /sys/kernel/debug/$FAILTYPE/verbose + echo Y > /sys/kernel/debug/$FAILTYPE/ignore-gfp-wait +@@ -338,7 +336,7 @@ Application Examples + echo N > /sys/kernel/debug/$FAILTYPE/task-filter + echo 10 > /sys/kernel/debug/$FAILTYPE/probability + echo 100 > /sys/kernel/debug/$FAILTYPE/interval +- printf %#x -1 > /sys/kernel/debug/$FAILTYPE/times ++ echo -1 > /sys/kernel/debug/$FAILTYPE/times + echo 0 > /sys/kernel/debug/$FAILTYPE/space + echo 2 > /sys/kernel/debug/$FAILTYPE/verbose + echo Y > /sys/kernel/debug/$FAILTYPE/ignore-gfp-wait +@@ -369,7 +367,7 @@ Application Examples + echo N > /sys/kernel/debug/$FAILTYPE/task-filter + echo 100 > /sys/kernel/debug/$FAILTYPE/probability + echo 0 > /sys/kernel/debug/$FAILTYPE/interval +- printf %#x -1 > /sys/kernel/debug/$FAILTYPE/times ++ echo -1 > /sys/kernel/debug/$FAILTYPE/times + echo 0 > /sys/kernel/debug/$FAILTYPE/space + echo 1 > /sys/kernel/debug/$FAILTYPE/verbose + +diff --git a/Documentation/security/keys/trusted-encrypted.rst b/Documentation/security/keys/trusted-encrypted.rst +index 0bfb4c3397489..9bc9db8ec6517 100644 +--- a/Documentation/security/keys/trusted-encrypted.rst ++++ b/Documentation/security/keys/trusted-encrypted.rst +@@ -350,7 +350,8 @@ Load an encrypted key "evm" from saved blob:: + + Instantiate an encrypted key "evm" using user-provided decrypted data:: + +- $ keyctl add encrypted evm "new default user:kmk 32 `cat evm_decrypted_data.blob`" @u ++ $ evmkey=$(dd if=/dev/urandom bs=1 count=32 | xxd -c32 -p) ++ $ keyctl add encrypted evm "new default user:kmk 32 $evmkey" @u + 794890253 + + $ keyctl print 794890253 +diff --git a/Documentation/trace/kprobes.rst b/Documentation/trace/kprobes.rst +index 48cf778a24680..fc7ce76eab655 100644 +--- a/Documentation/trace/kprobes.rst ++++ b/Documentation/trace/kprobes.rst +@@ -131,8 +131,7 @@ For example, if the function is non-recursive and is called with a + spinlock held, maxactive = 1 should be enough. If the function is + non-recursive and can never relinquish the CPU (e.g., via a semaphore + or preemption), NR_CPUS should be enough. If maxactive <= 0, it is +-set to a default value. If CONFIG_PREEMPT is enabled, the default +-is max(10, 2*NR_CPUS). Otherwise, the default is NR_CPUS. ++set to a default value: max(10, 2*NR_CPUS). + + It's not a disaster if you set maxactive too low; you'll just miss + some probes. In the kretprobe struct, the nmissed field is set to +diff --git a/Makefile b/Makefile +index 997b677222920..a69d14983a489 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 1 +-SUBLEVEL = 0 ++SUBLEVEL = 3 + EXTRAVERSION = + NAME = Hurr durr I'ma ninja sloth + +diff --git a/arch/Kconfig b/arch/Kconfig +index 8f138e580d1ae..81599f5c17b0f 100644 +--- a/arch/Kconfig ++++ b/arch/Kconfig +@@ -635,7 +635,7 @@ config ARCH_SUPPORTS_SHADOW_CALL_STACK + config SHADOW_CALL_STACK + bool "Shadow Call Stack" + depends on ARCH_SUPPORTS_SHADOW_CALL_STACK +- depends on DYNAMIC_FTRACE_WITH_REGS || !FUNCTION_GRAPH_TRACER ++ depends on DYNAMIC_FTRACE_WITH_ARGS || DYNAMIC_FTRACE_WITH_REGS || !FUNCTION_GRAPH_TRACER + help + This option enables the compiler's Shadow Call Stack, which + uses a shadow stack to protect function return addresses from +diff --git a/arch/alpha/include/asm/thread_info.h b/arch/alpha/include/asm/thread_info.h +index fdc485d7787a6..084c27cb0c707 100644 +--- a/arch/alpha/include/asm/thread_info.h ++++ b/arch/alpha/include/asm/thread_info.h +@@ -75,7 +75,7 @@ register struct thread_info *__current_thread_info __asm__("$8"); + + /* Work to do on interrupt/exception return. */ + #define _TIF_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ +- _TIF_NOTIFY_RESUME) ++ _TIF_NOTIFY_RESUME | _TIF_NOTIFY_SIGNAL) + + /* Work to do on any return to userspace. */ + #define _TIF_ALLWORK_MASK (_TIF_WORK_MASK \ +diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S +index e227f3a29a43c..c41a5a9c3b9f2 100644 +--- a/arch/alpha/kernel/entry.S ++++ b/arch/alpha/kernel/entry.S +@@ -469,8 +469,10 @@ entSys: + #ifdef CONFIG_AUDITSYSCALL + lda $6, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT + and $3, $6, $3 +-#endif + bne $3, strace ++#else ++ blbs $3, strace /* check for SYSCALL_TRACE in disguise */ ++#endif + beq $4, 1f + ldq $27, 0($5) + 1: jsr $26, ($27), sys_ni_syscall +diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi +index 9dc928859ad33..2013a5ccecd31 100644 +--- a/arch/arm/boot/dts/armada-370.dtsi ++++ b/arch/arm/boot/dts/armada-370.dtsi +@@ -84,7 +84,7 @@ + + pcie2: pcie@2,0 { + device_type = "pci"; +- assigned-addresses = <0x82002800 0 0x80000 0 0x2000>; ++ assigned-addresses = <0x82001000 0 0x80000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +diff --git a/arch/arm/boot/dts/armada-375.dtsi b/arch/arm/boot/dts/armada-375.dtsi +index 929deaf312a55..c310ef26d1cce 100644 +--- a/arch/arm/boot/dts/armada-375.dtsi ++++ b/arch/arm/boot/dts/armada-375.dtsi +@@ -592,7 +592,7 @@ + + pcie1: pcie@2,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; ++ assigned-addresses = <0x82001000 0 0x44000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +diff --git a/arch/arm/boot/dts/armada-380.dtsi b/arch/arm/boot/dts/armada-380.dtsi +index ce1dddb2269b0..e94f22b0e9b5e 100644 +--- a/arch/arm/boot/dts/armada-380.dtsi ++++ b/arch/arm/boot/dts/armada-380.dtsi +@@ -89,7 +89,7 @@ + /* x1 port */ + pcie@2,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x40000 0 0x2000>; ++ assigned-addresses = <0x82001000 0 0x40000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -118,7 +118,7 @@ + /* x1 port */ + pcie@3,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; ++ assigned-addresses = <0x82001800 0 0x44000 0 0x2000>; + reg = <0x1800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +diff --git a/arch/arm/boot/dts/armada-385-turris-omnia.dts b/arch/arm/boot/dts/armada-385-turris-omnia.dts +index 72ac807cae259..0c1f238e4c306 100644 +--- a/arch/arm/boot/dts/armada-385-turris-omnia.dts ++++ b/arch/arm/boot/dts/armada-385-turris-omnia.dts +@@ -23,6 +23,12 @@ + stdout-path = &uart0; + }; + ++ aliases { ++ ethernet0 = ð0; ++ ethernet1 = ð1; ++ ethernet2 = ð2; ++ }; ++ + memory { + device_type = "memory"; + reg = <0x00000000 0x40000000>; /* 1024 MB */ +@@ -483,7 +489,17 @@ + }; + }; + +- /* port 6 is connected to eth0 */ ++ ports@6 { ++ reg = <6>; ++ label = "cpu"; ++ ethernet = <ð0>; ++ phy-mode = "rgmii-id"; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; + }; + }; + }; +diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi +index 83392b92dae28..be8d607c59b21 100644 +--- a/arch/arm/boot/dts/armada-385.dtsi ++++ b/arch/arm/boot/dts/armada-385.dtsi +@@ -93,7 +93,7 @@ + /* x1 port */ + pcie2: pcie@2,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x40000 0 0x2000>; ++ assigned-addresses = <0x82001000 0 0x40000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -121,7 +121,7 @@ + /* x1 port */ + pcie3: pcie@3,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; ++ assigned-addresses = <0x82001800 0 0x44000 0 0x2000>; + reg = <0x1800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -152,7 +152,7 @@ + */ + pcie4: pcie@4,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x48000 0 0x2000>; ++ assigned-addresses = <0x82002000 0 0x48000 0 0x2000>; + reg = <0x2000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +diff --git a/arch/arm/boot/dts/armada-39x.dtsi b/arch/arm/boot/dts/armada-39x.dtsi +index 923b035a3ab38..9d1cac49c022f 100644 +--- a/arch/arm/boot/dts/armada-39x.dtsi ++++ b/arch/arm/boot/dts/armada-39x.dtsi +@@ -463,7 +463,7 @@ + /* x1 port */ + pcie@2,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x40000 0 0x2000>; ++ assigned-addresses = <0x82001000 0 0x40000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -492,7 +492,7 @@ + /* x1 port */ + pcie@3,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; ++ assigned-addresses = <0x82001800 0 0x44000 0 0x2000>; + reg = <0x1800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -524,7 +524,7 @@ + */ + pcie@4,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x48000 0 0x2000>; ++ assigned-addresses = <0x82002000 0 0x48000 0 0x2000>; + reg = <0x2000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi +index bf9360f41e0a6..5ea9d509cd308 100644 +--- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi ++++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi +@@ -107,7 +107,7 @@ + + pcie2: pcie@2,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; ++ assigned-addresses = <0x82001000 0 0x44000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -135,7 +135,7 @@ + + pcie3: pcie@3,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x48000 0 0x2000>; ++ assigned-addresses = <0x82001800 0 0x48000 0 0x2000>; + reg = <0x1800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -163,7 +163,7 @@ + + pcie4: pcie@4,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x4c000 0 0x2000>; ++ assigned-addresses = <0x82002000 0 0x4c000 0 0x2000>; + reg = <0x2000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -191,7 +191,7 @@ + + pcie5: pcie@5,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x80000 0 0x2000>; ++ assigned-addresses = <0x82002800 0 0x80000 0 0x2000>; + reg = <0x2800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi +index 0714af52e6075..6c6fbb9faf5ac 100644 +--- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi ++++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi +@@ -122,7 +122,7 @@ + + pcie2: pcie@2,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; ++ assigned-addresses = <0x82001000 0 0x44000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -150,7 +150,7 @@ + + pcie3: pcie@3,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x48000 0 0x2000>; ++ assigned-addresses = <0x82001800 0 0x48000 0 0x2000>; + reg = <0x1800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -178,7 +178,7 @@ + + pcie4: pcie@4,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x4c000 0 0x2000>; ++ assigned-addresses = <0x82002000 0 0x4c000 0 0x2000>; + reg = <0x2000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -206,7 +206,7 @@ + + pcie5: pcie@5,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x80000 0 0x2000>; ++ assigned-addresses = <0x82002800 0 0x80000 0 0x2000>; + reg = <0x2800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -234,7 +234,7 @@ + + pcie6: pcie@6,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x84000 0 0x2000>; ++ assigned-addresses = <0x82003000 0 0x84000 0 0x2000>; + reg = <0x3000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -262,7 +262,7 @@ + + pcie7: pcie@7,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x88000 0 0x2000>; ++ assigned-addresses = <0x82003800 0 0x88000 0 0x2000>; + reg = <0x3800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -290,7 +290,7 @@ + + pcie8: pcie@8,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x8c000 0 0x2000>; ++ assigned-addresses = <0x82004000 0 0x8c000 0 0x2000>; + reg = <0x4000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -318,7 +318,7 @@ + + pcie9: pcie@9,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x42000 0 0x2000>; ++ assigned-addresses = <0x82004800 0 0x42000 0 0x2000>; + reg = <0x4800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +diff --git a/arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts b/arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts +index a6a2bc3b855c2..fcc890e3ad735 100644 +--- a/arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts ++++ b/arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts +@@ -162,16 +162,9 @@ + #size-cells = <1>; + ranges; + +- /* LPC FW cycle bridge region requires natural alignment */ +- flash_memory: region@b8000000 { +- no-map; +- reg = <0xb8000000 0x04000000>; /* 64M */ +- }; +- +- /* 48MB region from the end of flash to start of vga memory */ +- ramoops@bc000000 { ++ ramoops@b3e00000 { + compatible = "ramoops"; +- reg = <0xbc000000 0x200000>; /* 16 * (4 * 0x8000) */ ++ reg = <0xb3e00000 0x200000>; /* 16 * (4 * 0x8000) */ + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x8000>; +@@ -179,6 +172,12 @@ + max-reason = <3>; /* KMSG_DUMP_EMERG */ + }; + ++ /* LPC FW cycle bridge region requires natural alignment */ ++ flash_memory: region@b4000000 { ++ no-map; ++ reg = <0xb4000000 0x04000000>; /* 64M */ ++ }; ++ + /* VGA region is dictated by hardware strapping */ + vga_memory: region@bf000000 { + no-map; +diff --git a/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts b/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts +index bf59a9962379d..4879da4cdbd25 100644 +--- a/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts ++++ b/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts +@@ -95,14 +95,9 @@ + #size-cells = <1>; + ranges; + +- flash_memory: region@b8000000 { +- no-map; +- reg = <0xb8000000 0x04000000>; /* 64M */ +- }; +- +- ramoops@bc000000 { ++ ramoops@b3e00000 { + compatible = "ramoops"; +- reg = <0xbc000000 0x200000>; /* 16 * (4 * 0x8000) */ ++ reg = <0xb3e00000 0x200000>; /* 16 * (4 * 0x8000) */ + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x8000>; +@@ -110,6 +105,13 @@ + max-reason = <3>; /* KMSG_DUMP_EMERG */ + }; + ++ /* LPC FW cycle bridge region requires natural alignment */ ++ flash_memory: region@b4000000 { ++ no-map; ++ reg = <0xb4000000 0x04000000>; /* 64M */ ++ }; ++ ++ /* VGA region is dictated by hardware strapping */ + vga_memory: region@bf000000 { + no-map; + compatible = "shared-dma-pool"; +diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi +index 00a36fba2fd23..9aee3cfd3e981 100644 +--- a/arch/arm/boot/dts/dove.dtsi ++++ b/arch/arm/boot/dts/dove.dtsi +@@ -139,7 +139,7 @@ + pcie1: pcie@2 { + device_type = "pci"; + status = "disabled"; +- assigned-addresses = <0x82002800 0 0x80000 0 0x2000>; ++ assigned-addresses = <0x82001000 0 0x80000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + clocks = <&gate_clk 5>; + marvell,pcie-port = <1>; +diff --git a/arch/arm/boot/dts/nuvoton-npcm730-gbs.dts b/arch/arm/boot/dts/nuvoton-npcm730-gbs.dts +index d10669fcd527d..9e9eba8bad5e4 100644 +--- a/arch/arm/boot/dts/nuvoton-npcm730-gbs.dts ++++ b/arch/arm/boot/dts/nuvoton-npcm730-gbs.dts +@@ -366,7 +366,7 @@ + spi-max-frequency = <20000000>; + spi-rx-bus-width = <2>; + label = "bmc"; +- partitions@80000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +diff --git a/arch/arm/boot/dts/nuvoton-npcm730-gsj.dts b/arch/arm/boot/dts/nuvoton-npcm730-gsj.dts +index 491606c4f044d..2a394cc15284c 100644 +--- a/arch/arm/boot/dts/nuvoton-npcm730-gsj.dts ++++ b/arch/arm/boot/dts/nuvoton-npcm730-gsj.dts +@@ -142,7 +142,7 @@ + reg = <0>; + spi-rx-bus-width = <2>; + +- partitions@80000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +diff --git a/arch/arm/boot/dts/nuvoton-npcm730-kudo.dts b/arch/arm/boot/dts/nuvoton-npcm730-kudo.dts +index a0c2d76526258..f7b38bee039bc 100644 +--- a/arch/arm/boot/dts/nuvoton-npcm730-kudo.dts ++++ b/arch/arm/boot/dts/nuvoton-npcm730-kudo.dts +@@ -388,7 +388,7 @@ + spi-max-frequency = <5000000>; + spi-rx-bus-width = <2>; + label = "bmc"; +- partitions@80000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +@@ -422,7 +422,7 @@ + reg = <1>; + spi-max-frequency = <5000000>; + spi-rx-bus-width = <2>; +- partitions@88000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +@@ -447,7 +447,7 @@ + reg = <0>; + spi-max-frequency = <5000000>; + spi-rx-bus-width = <2>; +- partitions@A0000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +diff --git a/arch/arm/boot/dts/nuvoton-npcm750-evb.dts b/arch/arm/boot/dts/nuvoton-npcm750-evb.dts +index 3dad32834e5ea..f53d45fa1de87 100644 +--- a/arch/arm/boot/dts/nuvoton-npcm750-evb.dts ++++ b/arch/arm/boot/dts/nuvoton-npcm750-evb.dts +@@ -74,7 +74,7 @@ + spi-rx-bus-width = <2>; + reg = <0>; + spi-max-frequency = <5000000>; +- partitions@80000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +@@ -135,7 +135,7 @@ + spi-rx-bus-width = <2>; + reg = <0>; + spi-max-frequency = <5000000>; +- partitions@A0000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +diff --git a/arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts b/arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts +index 132e702281fc5..87359ab05db3e 100644 +--- a/arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts ++++ b/arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts +@@ -107,7 +107,7 @@ + reg = <0>; + spi-rx-bus-width = <2>; + +- partitions@80000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +@@ -146,7 +146,7 @@ + reg = <1>; + npcm,fiu-rx-bus-width = <2>; + +- partitions@88000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +@@ -173,7 +173,7 @@ + reg = <0>; + spi-rx-bus-width = <2>; + +- partitions@A0000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi +index 942aa2278355d..a39b940d58532 100644 +--- a/arch/arm/boot/dts/qcom-apq8064.dtsi ++++ b/arch/arm/boot/dts/qcom-apq8064.dtsi +@@ -1615,7 +1615,7 @@ + }; + + etb@1a01000 { +- compatible = "coresight-etb10", "arm,primecell"; ++ compatible = "arm,coresight-etb10", "arm,primecell"; + reg = <0x1a01000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>; +diff --git a/arch/arm/boot/dts/spear600.dtsi b/arch/arm/boot/dts/spear600.dtsi +index fd41243a0b2c0..9d5a04a46b14e 100644 +--- a/arch/arm/boot/dts/spear600.dtsi ++++ b/arch/arm/boot/dts/spear600.dtsi +@@ -47,7 +47,7 @@ + compatible = "arm,pl110", "arm,primecell"; + reg = <0xfc200000 0x1000>; + interrupt-parent = <&vic1>; +- interrupts = <12>; ++ interrupts = <13>; + status = "disabled"; + }; + +diff --git a/arch/arm/boot/dts/stm32mp157a-dhcor-avenger96.dts b/arch/arm/boot/dts/stm32mp157a-dhcor-avenger96.dts +index 2e3c9fbb4eb36..275167f26fd9d 100644 +--- a/arch/arm/boot/dts/stm32mp157a-dhcor-avenger96.dts ++++ b/arch/arm/boot/dts/stm32mp157a-dhcor-avenger96.dts +@@ -13,7 +13,6 @@ + /dts-v1/; + + #include "stm32mp157.dtsi" +-#include "stm32mp15xc.dtsi" + #include "stm32mp15xx-dhcor-som.dtsi" + #include "stm32mp15xx-dhcor-avenger96.dtsi" + +diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi b/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi +index 90933077d66de..b6957cbdeff5f 100644 +--- a/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi ++++ b/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi +@@ -100,7 +100,7 @@ + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + +- gpios = <&gpioz 3 GPIO_ACTIVE_HIGH>; ++ gpio = <&gpioz 3 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + }; +diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c +index 41b2e8abc9e69..708816caf859c 100644 +--- a/arch/arm/mach-mmp/time.c ++++ b/arch/arm/mach-mmp/time.c +@@ -43,18 +43,21 @@ + static void __iomem *mmp_timer_base = TIMERS_VIRT_BASE; + + /* +- * FIXME: the timer needs some delay to stablize the counter capture ++ * Read the timer through the CVWR register. Delay is required after requesting ++ * a read. The CR register cannot be directly read due to metastability issues ++ * documented in the PXA168 software manual. + */ + static inline uint32_t timer_read(void) + { +- int delay = 100; ++ uint32_t val; ++ int delay = 3; + + __raw_writel(1, mmp_timer_base + TMR_CVWR(1)); + + while (delay--) +- cpu_relax(); ++ val = __raw_readl(mmp_timer_base + TMR_CVWR(1)); + +- return __raw_readl(mmp_timer_base + TMR_CVWR(1)); ++ return val; + } + + static u64 notrace mmp_read_sched_clock(void) +diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi +index 51a63b29d4045..a4d195e9eb8c8 100644 +--- a/arch/arm64/boot/dts/apple/t8103.dtsi ++++ b/arch/arm64/boot/dts/apple/t8103.dtsi +@@ -412,7 +412,7 @@ + resets = <&ps_ans2>; + }; + +- pcie0_dart_0: dart@681008000 { ++ pcie0_dart_0: iommu@681008000 { + compatible = "apple,t8103-dart"; + reg = <0x6 0x81008000 0x0 0x4000>; + #iommu-cells = <1>; +@@ -421,7 +421,7 @@ + power-domains = <&ps_apcie_gp>; + }; + +- pcie0_dart_1: dart@682008000 { ++ pcie0_dart_1: iommu@682008000 { + compatible = "apple,t8103-dart"; + reg = <0x6 0x82008000 0x0 0x4000>; + #iommu-cells = <1>; +@@ -430,7 +430,7 @@ + power-domains = <&ps_apcie_gp>; + }; + +- pcie0_dart_2: dart@683008000 { ++ pcie0_dart_2: iommu@683008000 { + compatible = "apple,t8103-dart"; + reg = <0x6 0x83008000 0x0 0x4000>; + #iommu-cells = <1>; +diff --git a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts +index ada164d423f3d..200f97e1c4c9c 100644 +--- a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts ++++ b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts +@@ -125,9 +125,12 @@ + /delete-property/ mrvl,i2c-fast-mode; + status = "okay"; + ++ /* MCP7940MT-I/MNY RTC */ + rtc@6f { + compatible = "microchip,mcp7940x"; + reg = <0x6f>; ++ interrupt-parent = <&gpiosb>; ++ interrupts = <5 0>; /* GPIO2_5 */ + }; + }; + +diff --git a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts +index 9b1af9c801308..d31a194124c91 100644 +--- a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts +@@ -26,14 +26,14 @@ + stdout-path = "serial0:921600n8"; + }; + +- cpus_fixed_vproc0: fixedregulator@0 { ++ cpus_fixed_vproc0: regulator-vproc-buck0 { + compatible = "regulator-fixed"; + regulator-name = "vproc_buck0"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + }; + +- cpus_fixed_vproc1: fixedregulator@1 { ++ cpus_fixed_vproc1: regulator-vproc-buck1 { + compatible = "regulator-fixed"; + regulator-name = "vproc_buck1"; + regulator-min-microvolt = <1000000>; +@@ -50,7 +50,7 @@ + id-gpio = <&pio 14 GPIO_ACTIVE_HIGH>; + }; + +- usb_p0_vbus: regulator@2 { ++ usb_p0_vbus: regulator-usb-p0-vbus { + compatible = "regulator-fixed"; + regulator-name = "p0_vbus"; + regulator-min-microvolt = <5000000>; +@@ -59,7 +59,7 @@ + enable-active-high; + }; + +- usb_p1_vbus: regulator@3 { ++ usb_p1_vbus: regulator-usb-p1-vbus { + compatible = "regulator-fixed"; + regulator-name = "p1_vbus"; + regulator-min-microvolt = <5000000>; +@@ -68,7 +68,7 @@ + enable-active-high; + }; + +- usb_p2_vbus: regulator@4 { ++ usb_p2_vbus: regulator-usb-p2-vbus { + compatible = "regulator-fixed"; + regulator-name = "p2_vbus"; + regulator-min-microvolt = <5000000>; +@@ -77,7 +77,7 @@ + enable-active-high; + }; + +- usb_p3_vbus: regulator@5 { ++ usb_p3_vbus: regulator-usb-p3-vbus { + compatible = "regulator-fixed"; + regulator-name = "p3_vbus"; + regulator-min-microvolt = <5000000>; +diff --git a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi +index e6d7453e56e0e..1ac0b2cf3d406 100644 +--- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi +@@ -160,70 +160,70 @@ + #clock-cells = <0>; + }; + +- clk26m: oscillator@0 { ++ clk26m: oscillator-26m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <26000000>; + clock-output-names = "clk26m"; + }; + +- clk32k: oscillator@1 { ++ clk32k: oscillator-32k { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "clk32k"; + }; + +- clkfpc: oscillator@2 { ++ clkfpc: oscillator-50m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <50000000>; + clock-output-names = "clkfpc"; + }; + +- clkaud_ext_i_0: oscillator@3 { ++ clkaud_ext_i_0: oscillator-aud0 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <6500000>; + clock-output-names = "clkaud_ext_i_0"; + }; + +- clkaud_ext_i_1: oscillator@4 { ++ clkaud_ext_i_1: oscillator-aud1 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <196608000>; + clock-output-names = "clkaud_ext_i_1"; + }; + +- clkaud_ext_i_2: oscillator@5 { ++ clkaud_ext_i_2: oscillator-aud2 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <180633600>; + clock-output-names = "clkaud_ext_i_2"; + }; + +- clki2si0_mck_i: oscillator@6 { ++ clki2si0_mck_i: oscillator-i2s0 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <30000000>; + clock-output-names = "clki2si0_mck_i"; + }; + +- clki2si1_mck_i: oscillator@7 { ++ clki2si1_mck_i: oscillator-i2s1 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <30000000>; + clock-output-names = "clki2si1_mck_i"; + }; + +- clki2si2_mck_i: oscillator@8 { ++ clki2si2_mck_i: oscillator-i2s2 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <30000000>; + clock-output-names = "clki2si2_mck_i"; + }; + +- clktdmin_mclk_i: oscillator@9 { ++ clktdmin_mclk_i: oscillator-mclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <30000000>; +@@ -266,7 +266,7 @@ + reg = <0 0x10005000 0 0x1000>; + }; + +- pio: pinctrl@10005000 { ++ pio: pinctrl@1000b000 { + compatible = "mediatek,mt2712-pinctrl"; + reg = <0 0x1000b000 0 0x1000>; + mediatek,pctl-regmap = <&syscfg_pctl_a>; +diff --git a/arch/arm64/boot/dts/mediatek/mt6779.dtsi b/arch/arm64/boot/dts/mediatek/mt6779.dtsi +index 9bdf5145966c5..dde9ce137b4f1 100644 +--- a/arch/arm64/boot/dts/mediatek/mt6779.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt6779.dtsi +@@ -88,14 +88,14 @@ + interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW 0>; + }; + +- clk26m: oscillator@0 { ++ clk26m: oscillator-26m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <26000000>; + clock-output-names = "clk26m"; + }; + +- clk32k: oscillator@1 { ++ clk32k: oscillator-32k { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; +@@ -117,7 +117,7 @@ + compatible = "simple-bus"; + ranges; + +- gic: interrupt-controller@0c000000 { ++ gic: interrupt-controller@c000000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <4>; + interrupt-parent = <&gic>; +@@ -138,7 +138,7 @@ + + }; + +- sysirq: intpol-controller@0c53a650 { ++ sysirq: intpol-controller@c53a650 { + compatible = "mediatek,mt6779-sysirq", + "mediatek,mt6577-sysirq"; + interrupt-controller; +diff --git a/arch/arm64/boot/dts/mediatek/mt6797.dtsi b/arch/arm64/boot/dts/mediatek/mt6797.dtsi +index 15616231022a2..c3677d77e0a45 100644 +--- a/arch/arm64/boot/dts/mediatek/mt6797.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt6797.dtsi +@@ -95,7 +95,7 @@ + }; + }; + +- clk26m: oscillator@0 { ++ clk26m: oscillator-26m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <26000000>; +diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +index 72e0d9722e07a..35e01fa2d314b 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -14,7 +14,7 @@ + #address-cells = <2>; + #size-cells = <2>; + +- clk40m: oscillator@0 { ++ clk40m: oscillator-40m { + compatible = "fixed-clock"; + clock-frequency = <40000000>; + #clock-cells = <0>; +@@ -112,6 +112,12 @@ + #clock-cells = <1>; + }; + ++ wed_pcie: wed-pcie@10003000 { ++ compatible = "mediatek,mt7986-wed-pcie", ++ "syscon"; ++ reg = <0 0x10003000 0 0x10>; ++ }; ++ + topckgen: topckgen@1001b000 { + compatible = "mediatek,mt7986-topckgen", "syscon"; + reg = <0 0x1001B000 0 0x1000>; +@@ -168,7 +174,7 @@ + #clock-cells = <1>; + }; + +- trng: trng@1020f000 { ++ trng: rng@1020f000 { + compatible = "mediatek,mt7986-rng", + "mediatek,mt7623-rng"; + reg = <0 0x1020f000 0 0x100>; +@@ -228,12 +234,6 @@ + #reset-cells = <1>; + }; + +- wed_pcie: wed-pcie@10003000 { +- compatible = "mediatek,mt7986-wed-pcie", +- "syscon"; +- reg = <0 0x10003000 0 0x10>; +- }; +- + wed0: wed@15010000 { + compatible = "mediatek,mt7986-wed", + "syscon"; +diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi +index a70b669c49baa..402136bfd5350 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi +@@ -1678,7 +1678,7 @@ + <GIC_SPI 278 IRQ_TYPE_LEVEL_LOW>; + interrupt-names = "job", "mmu", "gpu"; + +- clocks = <&topckgen CLK_TOP_MFGPLL_CK>; ++ clocks = <&mfgcfg CLK_MFG_BG3D>; + + power-domains = + <&spm MT8183_POWER_DOMAIN_MFG_CORE0>, +diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi +index 905d1a90b406c..0b85b5874a4f9 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi +@@ -36,7 +36,7 @@ + enable-method = "psci"; + performance-domains = <&performance 0>; + clock-frequency = <1701000000>; +- capacity-dmips-mhz = <578>; ++ capacity-dmips-mhz = <308>; + cpu-idle-states = <&cpu_off_l &cluster_off_l>; + next-level-cache = <&l2_0>; + #cooling-cells = <2>; +@@ -49,7 +49,7 @@ + enable-method = "psci"; + performance-domains = <&performance 0>; + clock-frequency = <1701000000>; +- capacity-dmips-mhz = <578>; ++ capacity-dmips-mhz = <308>; + cpu-idle-states = <&cpu_off_l &cluster_off_l>; + next-level-cache = <&l2_0>; + #cooling-cells = <2>; +@@ -62,7 +62,7 @@ + enable-method = "psci"; + performance-domains = <&performance 0>; + clock-frequency = <1701000000>; +- capacity-dmips-mhz = <578>; ++ capacity-dmips-mhz = <308>; + cpu-idle-states = <&cpu_off_l &cluster_off_l>; + next-level-cache = <&l2_0>; + #cooling-cells = <2>; +@@ -75,7 +75,7 @@ + enable-method = "psci"; + performance-domains = <&performance 0>; + clock-frequency = <1701000000>; +- capacity-dmips-mhz = <578>; ++ capacity-dmips-mhz = <308>; + cpu-idle-states = <&cpu_off_l &cluster_off_l>; + next-level-cache = <&l2_0>; + #cooling-cells = <2>; +diff --git a/arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi b/arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi +index 8ee1529683a34..ec8dfb3d1c6d6 100644 +--- a/arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi ++++ b/arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi +@@ -17,7 +17,7 @@ + }; + + firmware { +- optee: optee@4fd00000 { ++ optee: optee { + compatible = "linaro,optee-tz"; + method = "smc"; + }; +@@ -209,7 +209,7 @@ + }; + }; + +- i2c0_pins_a: i2c0@0 { ++ i2c0_pins_a: i2c0 { + pins1 { + pinmux = <MT8516_PIN_58_SDA0__FUNC_SDA0_0>, + <MT8516_PIN_59_SCL0__FUNC_SCL0_0>; +@@ -217,7 +217,7 @@ + }; + }; + +- i2c2_pins_a: i2c2@0 { ++ i2c2_pins_a: i2c2 { + pins1 { + pinmux = <MT8516_PIN_60_SDA2__FUNC_SDA2_0>, + <MT8516_PIN_61_SCL2__FUNC_SCL2_0>; +diff --git a/arch/arm64/boot/dts/nvidia/tegra234.dtsi b/arch/arm64/boot/dts/nvidia/tegra234.dtsi +index 0170bfa8a4679..dfe2cf2f4b218 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra234.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra234.dtsi +@@ -1965,7 +1965,7 @@ + + bus-range = <0x0 0xff>; + +- ranges = <0x43000000 0x35 0x40000000 0x35 0x40000000 0x2 0xe8000000>, /* prefetchable memory (11904 MB) */ ++ ranges = <0x43000000 0x35 0x40000000 0x35 0x40000000 0x2 0xc0000000>, /* prefetchable memory (11264 MB) */ + <0x02000000 0x0 0x40000000 0x38 0x28000000 0x0 0x08000000>, /* non-prefetchable memory (128 MB) */ + <0x01000000 0x0 0x2c100000 0x00 0x2c100000 0x0 0x00100000>; /* downstream I/O (1 MB) */ + +@@ -2178,7 +2178,7 @@ + bus-range = <0x0 0xff>; + + ranges = <0x43000000 0x21 0x00000000 0x21 0x00000000 0x0 0x28000000>, /* prefetchable memory (640 MB) */ +- <0x02000000 0x0 0x40000000 0x21 0xe8000000 0x0 0x08000000>, /* non-prefetchable memory (128 MB) */ ++ <0x02000000 0x0 0x40000000 0x21 0x28000000 0x0 0x08000000>, /* non-prefetchable memory (128 MB) */ + <0x01000000 0x0 0x34100000 0x00 0x34100000 0x0 0x00100000>; /* downstream I/O (1 MB) */ + + interconnects = <&mc TEGRA234_MEMORY_CLIENT_PCIE3R &emc>, +@@ -2336,7 +2336,7 @@ + + bus-range = <0x0 0xff>; + +- ranges = <0x43000000 0x27 0x40000000 0x27 0x40000000 0x3 0xe8000000>, /* prefetchable memory (16000 MB) */ ++ ranges = <0x43000000 0x28 0x00000000 0x28 0x00000000 0x3 0x28000000>, /* prefetchable memory (12928 MB) */ + <0x02000000 0x0 0x40000000 0x2b 0x28000000 0x0 0x08000000>, /* non-prefetchable memory (128 MB) */ + <0x01000000 0x0 0x3a100000 0x00 0x3a100000 0x0 0x00100000>; /* downstream I/O (1 MB) */ + +@@ -2442,7 +2442,7 @@ + + bus-range = <0x0 0xff>; + +- ranges = <0x43000000 0x2e 0x40000000 0x2e 0x40000000 0x3 0xe8000000>, /* prefetchable memory (16000 MB) */ ++ ranges = <0x43000000 0x30 0x00000000 0x30 0x00000000 0x2 0x28000000>, /* prefetchable memory (8832 MB) */ + <0x02000000 0x0 0x40000000 0x32 0x28000000 0x0 0x08000000>, /* non-prefetchable memory (128 MB) */ + <0x01000000 0x0 0x3e100000 0x00 0x3e100000 0x0 0x00100000>; /* downstream I/O (1 MB) */ + +diff --git a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts +index 1ba2eca33c7b6..6a716c83e5f1d 100644 +--- a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts ++++ b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts +@@ -37,6 +37,8 @@ + + &blsp1_spi1 { + cs-select = <0>; ++ pinctrl-0 = <&spi_0_pins>; ++ pinctrl-names = "default"; + status = "okay"; + + flash@0 { +diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi +index a831064700ee8..9743cb270639d 100644 +--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi ++++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi +@@ -1345,7 +1345,7 @@ + }; + + mpss: remoteproc@4080000 { +- compatible = "qcom,msm8916-mss-pil", "qcom,q6v5-pil"; ++ compatible = "qcom,msm8916-mss-pil"; + reg = <0x04080000 0x100>, + <0x04020000 0x040>; + +diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi +index aba7176443919..1107befc3b091 100644 +--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi ++++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi +@@ -144,82 +144,92 @@ + /* Nominal fmax for now */ + opp-307200000 { + opp-hz = /bits/ 64 <307200000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-422400000 { + opp-hz = /bits/ 64 <422400000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-556800000 { + opp-hz = /bits/ 64 <556800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-652800000 { + opp-hz = /bits/ 64 <652800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-729600000 { + opp-hz = /bits/ 64 <729600000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-844800000 { + opp-hz = /bits/ 64 <844800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-960000000 { + opp-hz = /bits/ 64 <960000000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1036800000 { + opp-hz = /bits/ 64 <1036800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1113600000 { + opp-hz = /bits/ 64 <1113600000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1190400000 { + opp-hz = /bits/ 64 <1190400000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1228800000 { + opp-hz = /bits/ 64 <1228800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1324800000 { + opp-hz = /bits/ 64 <1324800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x5>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1363200000 { ++ opp-hz = /bits/ 64 <1363200000>; ++ opp-supported-hw = <0x2>; + clock-latency-ns = <200000>; + }; + opp-1401600000 { + opp-hz = /bits/ 64 <1401600000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x5>; + clock-latency-ns = <200000>; + }; + opp-1478400000 { + opp-hz = /bits/ 64 <1478400000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x1>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1497600000 { ++ opp-hz = /bits/ 64 <1497600000>; ++ opp-supported-hw = <0x04>; + clock-latency-ns = <200000>; + }; + opp-1593600000 { + opp-hz = /bits/ 64 <1593600000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x1>; + clock-latency-ns = <200000>; + }; + }; +@@ -232,127 +242,137 @@ + /* Nominal fmax for now */ + opp-307200000 { + opp-hz = /bits/ 64 <307200000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-403200000 { + opp-hz = /bits/ 64 <403200000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-556800000 { + opp-hz = /bits/ 64 <556800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-652800000 { + opp-hz = /bits/ 64 <652800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-729600000 { + opp-hz = /bits/ 64 <729600000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-806400000 { + opp-hz = /bits/ 64 <806400000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-883200000 { + opp-hz = /bits/ 64 <883200000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-940800000 { + opp-hz = /bits/ 64 <940800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1036800000 { + opp-hz = /bits/ 64 <1036800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1113600000 { + opp-hz = /bits/ 64 <1113600000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1190400000 { + opp-hz = /bits/ 64 <1190400000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1248000000 { + opp-hz = /bits/ 64 <1248000000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1324800000 { + opp-hz = /bits/ 64 <1324800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1401600000 { + opp-hz = /bits/ 64 <1401600000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1478400000 { + opp-hz = /bits/ 64 <1478400000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1555200000 { + opp-hz = /bits/ 64 <1555200000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1632000000 { + opp-hz = /bits/ 64 <1632000000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1708800000 { + opp-hz = /bits/ 64 <1708800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1785600000 { + opp-hz = /bits/ 64 <1785600000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1804800000 { ++ opp-hz = /bits/ 64 <1804800000>; ++ opp-supported-hw = <0x6>; + clock-latency-ns = <200000>; + }; + opp-1824000000 { + opp-hz = /bits/ 64 <1824000000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x1>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1900800000 { ++ opp-hz = /bits/ 64 <1900800000>; ++ opp-supported-hw = <0x4>; + clock-latency-ns = <200000>; + }; + opp-1920000000 { + opp-hz = /bits/ 64 <1920000000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x1>; + clock-latency-ns = <200000>; + }; + opp-1996800000 { + opp-hz = /bits/ 64 <1996800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x1>; + clock-latency-ns = <200000>; + }; + opp-2073600000 { + opp-hz = /bits/ 64 <2073600000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x1>; + clock-latency-ns = <200000>; + }; + opp-2150400000 { + opp-hz = /bits/ 64 <2150400000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x1>; + clock-latency-ns = <200000>; + }; + }; +@@ -1213,17 +1233,17 @@ + compatible = "operating-points-v2"; + + /* +- * 624Mhz and 560Mhz are only available on speed +- * bin (1 << 0). All the rest are available on +- * all bins of the hardware ++ * 624Mhz is only available on speed bins 0 and 3. ++ * 560Mhz is only available on speed bins 0, 2 and 3. ++ * All the rest are available on all bins of the hardware. + */ + opp-624000000 { + opp-hz = /bits/ 64 <624000000>; +- opp-supported-hw = <0x01>; ++ opp-supported-hw = <0x09>; + }; + opp-560000000 { + opp-hz = /bits/ 64 <560000000>; +- opp-supported-hw = <0x01>; ++ opp-supported-hw = <0x0d>; + }; + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; +@@ -3342,7 +3362,7 @@ + interrupt-names = "intr1", "intr2"; + interrupt-controller; + #interrupt-cells = <1>; +- reset-gpios = <&tlmm 64 GPIO_ACTIVE_HIGH>; ++ reset-gpios = <&tlmm 64 GPIO_ACTIVE_LOW>; + + slim-ifc-dev = <&tasha_ifd>; + +diff --git a/arch/arm64/boot/dts/qcom/msm8996pro.dtsi b/arch/arm64/boot/dts/qcom/msm8996pro.dtsi +new file mode 100644 +index 0000000000000..63e1b4ec7a360 +--- /dev/null ++++ b/arch/arm64/boot/dts/qcom/msm8996pro.dtsi +@@ -0,0 +1,266 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2022, Linaro Limited ++ */ ++ ++#include "msm8996.dtsi" ++ ++/ { ++ /delete-node/ opp-table-cluster0; ++ /delete-node/ opp-table-cluster1; ++ ++ /* ++ * On MSM8996 Pro the cpufreq driver shifts speed bins into the high ++ * nibble of supported hw, so speed bin 0 becomes 0x10, speed bin 1 ++ * becomes 0x20, speed 2 becomes 0x40. ++ */ ++ ++ cluster0_opp: opp-table-cluster0 { ++ compatible = "operating-points-v2-kryo-cpu"; ++ nvmem-cells = <&speedbin_efuse>; ++ opp-shared; ++ ++ opp-307200000 { ++ opp-hz = /bits/ 64 <307200000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-384000000 { ++ opp-hz = /bits/ 64 <384000000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-460800000 { ++ opp-hz = /bits/ 64 <460800000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-537600000 { ++ opp-hz = /bits/ 64 <537600000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-614400000 { ++ opp-hz = /bits/ 64 <614400000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-691200000 { ++ opp-hz = /bits/ 64 <691200000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-768000000 { ++ opp-hz = /bits/ 64 <768000000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-844800000 { ++ opp-hz = /bits/ 64 <844800000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-902400000 { ++ opp-hz = /bits/ 64 <902400000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-979200000 { ++ opp-hz = /bits/ 64 <979200000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1056000000 { ++ opp-hz = /bits/ 64 <1056000000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1132800000 { ++ opp-hz = /bits/ 64 <1132800000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1209600000 { ++ opp-hz = /bits/ 64 <1209600000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1286400000 { ++ opp-hz = /bits/ 64 <1286400000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1363200000 { ++ opp-hz = /bits/ 64 <1363200000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1440000000 { ++ opp-hz = /bits/ 64 <1440000000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1516800000 { ++ opp-hz = /bits/ 64 <1516800000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1593600000 { ++ opp-hz = /bits/ 64 <1593600000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1996800000 { ++ opp-hz = /bits/ 64 <1996800000>; ++ opp-supported-hw = <0x20>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-2188800000 { ++ opp-hz = /bits/ 64 <2188800000>; ++ opp-supported-hw = <0x10>; ++ clock-latency-ns = <200000>; ++ }; ++ }; ++ ++ cluster1_opp: opp-table-cluster1 { ++ compatible = "operating-points-v2-kryo-cpu"; ++ nvmem-cells = <&speedbin_efuse>; ++ opp-shared; ++ ++ opp-307200000 { ++ opp-hz = /bits/ 64 <307200000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-384000000 { ++ opp-hz = /bits/ 64 <384000000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-460800000 { ++ opp-hz = /bits/ 64 <460800000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-537600000 { ++ opp-hz = /bits/ 64 <537600000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-614400000 { ++ opp-hz = /bits/ 64 <614400000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-691200000 { ++ opp-hz = /bits/ 64 <691200000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-748800000 { ++ opp-hz = /bits/ 64 <748800000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-825600000 { ++ opp-hz = /bits/ 64 <825600000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-902400000 { ++ opp-hz = /bits/ 64 <902400000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-979200000 { ++ opp-hz = /bits/ 64 <979200000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1056000000 { ++ opp-hz = /bits/ 64 <1056000000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1132800000 { ++ opp-hz = /bits/ 64 <1132800000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1209600000 { ++ opp-hz = /bits/ 64 <1209600000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1286400000 { ++ opp-hz = /bits/ 64 <1286400000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1363200000 { ++ opp-hz = /bits/ 64 <1363200000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1440000000 { ++ opp-hz = /bits/ 64 <1440000000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1516800000 { ++ opp-hz = /bits/ 64 <1516800000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1593600000 { ++ opp-hz = /bits/ 64 <1593600000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1670400000 { ++ opp-hz = /bits/ 64 <1670400000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1747200000 { ++ opp-hz = /bits/ 64 <1747200000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1824000000 { ++ opp-hz = /bits/ 64 <1824000000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1900800000 { ++ opp-hz = /bits/ 64 <1900800000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1977600000 { ++ opp-hz = /bits/ 64 <1977600000>; ++ opp-supported-hw = <0x30>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-2054400000 { ++ opp-hz = /bits/ 64 <2054400000>; ++ opp-supported-hw = <0x30>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-2150400000 { ++ opp-hz = /bits/ 64 <2150400000>; ++ opp-supported-hw = <0x30>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-2246400000 { ++ opp-hz = /bits/ 64 <2246400000>; ++ opp-supported-hw = <0x10>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-2342400000 { ++ opp-hz = /bits/ 64 <2342400000>; ++ opp-supported-hw = <0x10>; ++ clock-latency-ns = <200000>; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/qcom/pm6350.dtsi b/arch/arm64/boot/dts/qcom/pm6350.dtsi +index ecf9b99191828..68245d78d2b93 100644 +--- a/arch/arm64/boot/dts/qcom/pm6350.dtsi ++++ b/arch/arm64/boot/dts/qcom/pm6350.dtsi +@@ -3,6 +3,7 @@ + * Copyright (c) 2021, Luca Weiss <luca@z3ntu.xyz> + */ + ++#include <dt-bindings/input/input.h> + #include <dt-bindings/spmi/spmi.h> + + &spmi_bus { +diff --git a/arch/arm64/boot/dts/qcom/pm660.dtsi b/arch/arm64/boot/dts/qcom/pm660.dtsi +index e1622b16c08bd..02a69ac0149b2 100644 +--- a/arch/arm64/boot/dts/qcom/pm660.dtsi ++++ b/arch/arm64/boot/dts/qcom/pm660.dtsi +@@ -163,7 +163,7 @@ + qcom,pre-scaling = <1 3>; + }; + +- vcoin: vcoin@83 { ++ vcoin: vcoin@85 { + reg = <ADC5_VCOIN>; + qcom,decimation = <1024>; + qcom,pre-scaling = <1 3>; +diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi +index 1bd6c7dcd9e91..bfab67f4a7c9c 100644 +--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi ++++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi +@@ -194,6 +194,12 @@ ap_ts_pen_1v8: &i2c4 { + pins = "gpio49", "gpio50", "gpio51", "gpio52"; + function = "mi2s_1"; + }; ++ ++ pinconf { ++ pins = "gpio49", "gpio50", "gpio51", "gpio52"; ++ drive-strength = <2>; ++ bias-pull-down; ++ }; + }; + + &ts_reset_l { +diff --git a/arch/arm64/boot/dts/qcom/sc7280-idp.dts b/arch/arm64/boot/dts/qcom/sc7280-idp.dts +index 7559164cdda08..e2e37a0292ad6 100644 +--- a/arch/arm64/boot/dts/qcom/sc7280-idp.dts ++++ b/arch/arm64/boot/dts/qcom/sc7280-idp.dts +@@ -10,7 +10,6 @@ + #include <dt-bindings/iio/qcom,spmi-adc7-pmr735a.h> + #include "sc7280-idp.dtsi" + #include "pmr735a.dtsi" +-#include "sc7280-herobrine-lte-sku.dtsi" + + / { + model = "Qualcomm Technologies, Inc. sc7280 IDP SKU1 platform"; +diff --git a/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi b/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi +index cd432a2856a7b..ca50f0ba9b815 100644 +--- a/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi ++++ b/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi +@@ -13,6 +13,7 @@ + #include "pmk8350.dtsi" + + #include "sc7280-chrome-common.dtsi" ++#include "sc7280-herobrine-lte-sku.dtsi" + + / { + aliases { +@@ -34,7 +35,7 @@ + pinctrl-0 = <&wcd_reset_n>; + pinctrl-1 = <&wcd_reset_n_sleep>; + +- reset-gpios = <&tlmm 83 GPIO_ACTIVE_HIGH>; ++ reset-gpios = <&tlmm 83 GPIO_ACTIVE_LOW>; + + qcom,rx-device = <&wcd_rx>; + qcom,tx-device = <&wcd_tx>; +diff --git a/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi b/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi +index 4b8c676b0bb19..f7665b3799233 100644 +--- a/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi ++++ b/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi +@@ -37,7 +37,7 @@ + pinctrl-0 = <&wcd_reset_n>, <&us_euro_hs_sel>; + pinctrl-1 = <&wcd_reset_n_sleep>, <&us_euro_hs_sel>; + +- reset-gpios = <&tlmm 83 GPIO_ACTIVE_HIGH>; ++ reset-gpios = <&tlmm 83 GPIO_ACTIVE_LOW>; + us-euro-gpios = <&tlmm 81 GPIO_ACTIVE_HIGH>; + + qcom,rx-device = <&wcd_rx>; +diff --git a/arch/arm64/boot/dts/qcom/sdm630.dtsi b/arch/arm64/boot/dts/qcom/sdm630.dtsi +index b51b85f583e5d..e119060ac56cb 100644 +--- a/arch/arm64/boot/dts/qcom/sdm630.dtsi ++++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi +@@ -779,7 +779,7 @@ + pins = "gpio17", "gpio18", "gpio19"; + function = "gpio"; + drive-strength = <2>; +- bias-no-pull; ++ bias-disable; + }; + }; + +diff --git a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi +index b5eb8f7eca1d5..b5f11fbcc3004 100644 +--- a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi ++++ b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi +@@ -1436,7 +1436,7 @@ ap_ts_i2c: &i2c14 { + config { + pins = "gpio126"; + function = "gpio"; +- bias-no-pull; ++ bias-disable; + drive-strength = <2>; + output-low; + }; +@@ -1446,7 +1446,7 @@ ap_ts_i2c: &i2c14 { + config { + pins = "gpio126"; + function = "gpio"; +- bias-no-pull; ++ bias-disable; + drive-strength = <2>; + output-high; + }; +diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts +index afc17e4d403fc..f982594896796 100644 +--- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts ++++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts +@@ -628,7 +628,7 @@ + }; + + wcd_intr_default: wcd-intr-default { +- pins = "goui54"; ++ pins = "gpio54"; + function = "gpio"; + input-enable; + bias-pull-down; +diff --git a/arch/arm64/boot/dts/qcom/sm6125.dtsi b/arch/arm64/boot/dts/qcom/sm6125.dtsi +index 1fe3fa3ad8770..7818fb6c5a10a 100644 +--- a/arch/arm64/boot/dts/qcom/sm6125.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm6125.dtsi +@@ -458,7 +458,7 @@ + sdhc_1: mmc@4744000 { + compatible = "qcom,sm6125-sdhci", "qcom,sdhci-msm-v5"; + reg = <0x04744000 0x1000>, <0x04745000 0x1000>; +- reg-names = "hc", "core"; ++ reg-names = "hc", "cqhci"; + + interrupts = <GIC_SPI 348 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>; +diff --git a/arch/arm64/boot/dts/qcom/sm6350.dtsi b/arch/arm64/boot/dts/qcom/sm6350.dtsi +index c39de7d3ace0b..7be5fc8dec671 100644 +--- a/arch/arm64/boot/dts/qcom/sm6350.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm6350.dtsi +@@ -485,6 +485,7 @@ + interrupts = <GIC_SPI 641 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 644 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "hc_irq", "pwr_irq"; ++ iommus = <&apps_smmu 0x60 0x0>; + + clocks = <&gcc GCC_SDCC1_AHB_CLK>, + <&gcc GCC_SDCC1_APPS_CLK>, +@@ -1063,6 +1064,7 @@ + interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "hc_irq", "pwr_irq"; ++ iommus = <&apps_smmu 0x560 0x0>; + + clocks = <&gcc GCC_SDCC2_AHB_CLK>, + <&gcc GCC_SDCC2_APPS_CLK>, +@@ -1148,15 +1150,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/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi +index cef8c4f4f0ff2..4a527a64772b4 100644 +--- a/arch/arm64/boot/dts/qcom/sm8150.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi +@@ -2032,11 +2032,11 @@ + status = "disabled"; + + ufs_mem_phy_lanes: phy@1d87400 { +- reg = <0 0x01d87400 0 0x108>, +- <0 0x01d87600 0 0x1e0>, +- <0 0x01d87c00 0 0x1dc>, +- <0 0x01d87800 0 0x108>, +- <0 0x01d87a00 0 0x1e0>; ++ reg = <0 0x01d87400 0 0x16c>, ++ <0 0x01d87600 0 0x200>, ++ <0 0x01d87c00 0 0x200>, ++ <0 0x01d87800 0 0x16c>, ++ <0 0x01d87a00 0 0x200>; + #phy-cells = <0>; + }; + }; +diff --git a/arch/arm64/boot/dts/qcom/sm8250-mtp.dts b/arch/arm64/boot/dts/qcom/sm8250-mtp.dts +index a102aa5efa326..a05fe468e0b41 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250-mtp.dts ++++ b/arch/arm64/boot/dts/qcom/sm8250-mtp.dts +@@ -635,7 +635,7 @@ + wcd938x: codec { + compatible = "qcom,wcd9380-codec"; + #sound-dai-cells = <1>; +- reset-gpios = <&tlmm 32 GPIO_ACTIVE_HIGH>; ++ reset-gpios = <&tlmm 32 GPIO_ACTIVE_LOW>; + vdd-buck-supply = <&vreg_s4a_1p8>; + vdd-rxtx-supply = <&vreg_s4a_1p8>; + vdd-io-supply = <&vreg_s4a_1p8>; +diff --git a/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi b/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi +index 5428aab3058dd..e4769dcfaad7b 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi +@@ -619,7 +619,7 @@ + pins = "gpio39"; + function = "gpio"; + drive-strength = <2>; +- bias-disabled; ++ bias-disable; + input-enable; + }; + +diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi +index e276eed1f8e2c..29e352a577311 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi +@@ -2180,11 +2180,11 @@ + status = "disabled"; + + ufs_mem_phy_lanes: phy@1d87400 { +- reg = <0 0x01d87400 0 0x108>, +- <0 0x01d87600 0 0x1e0>, +- <0 0x01d87c00 0 0x1dc>, +- <0 0x01d87800 0 0x108>, +- <0 0x01d87a00 0 0x1e0>; ++ reg = <0 0x01d87400 0 0x16c>, ++ <0 0x01d87600 0 0x200>, ++ <0 0x01d87c00 0 0x200>, ++ <0 0x01d87800 0 0x16c>, ++ <0 0x01d87a00 0 0x200>; + #phy-cells = <0>; + }; + }; +@@ -2455,7 +2455,7 @@ + pins = "gpio7"; + function = "dmic1_data"; + drive-strength = <2>; +- pull-down; ++ bias-pull-down; + input-enable; + }; + }; +@@ -2892,15 +2892,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/sm8350.dtsi b/arch/arm64/boot/dts/qcom/sm8350.dtsi +index a86d9ea93b9d4..a6270d97a3192 100644 +--- a/arch/arm64/boot/dts/qcom/sm8350.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8350.dtsi +@@ -2142,11 +2142,11 @@ + status = "disabled"; + + ufs_mem_phy_lanes: phy@1d87400 { +- reg = <0 0x01d87400 0 0x108>, +- <0 0x01d87600 0 0x1e0>, +- <0 0x01d87c00 0 0x1dc>, +- <0 0x01d87800 0 0x108>, +- <0 0x01d87a00 0 0x1e0>; ++ reg = <0 0x01d87400 0 0x188>, ++ <0 0x01d87600 0 0x200>, ++ <0 0x01d87c00 0 0x200>, ++ <0 0x01d87800 0 0x188>, ++ <0 0x01d87a00 0 0x200>; + #phy-cells = <0>; + }; + }; +diff --git a/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara-pdx223.dts b/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara-pdx223.dts +index d68765eb6d4f9..6351050bc87f2 100644 +--- a/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara-pdx223.dts ++++ b/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara-pdx223.dts +@@ -556,8 +556,6 @@ + pinctrl-1 = <&sdc2_sleep_state &sdc2_card_det_n>; + vmmc-supply = <&pm8350c_l9>; + vqmmc-supply = <&pm8350c_l6>; +- /* Forbid SDR104/SDR50 - broken hw! */ +- sdhci-caps-mask = <0x3 0x0>; + no-sdio; + no-mmc; + status = "okay"; +diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi +index d32f08df743d8..32a37c878a34c 100644 +--- a/arch/arm64/boot/dts/qcom/sm8450.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi +@@ -3161,11 +3161,11 @@ + status = "disabled"; + + ufs_mem_phy_lanes: phy@1d87400 { +- reg = <0 0x01d87400 0 0x108>, +- <0 0x01d87600 0 0x1e0>, +- <0 0x01d87c00 0 0x1dc>, +- <0 0x01d87800 0 0x108>, +- <0 0x01d87a00 0 0x1e0>; ++ reg = <0 0x01d87400 0 0x188>, ++ <0 0x01d87600 0 0x200>, ++ <0 0x01d87c00 0 0x200>, ++ <0 0x01d87800 0 0x188>, ++ <0 0x01d87a00 0 0x200>; + #phy-cells = <0>; + }; + }; +@@ -3192,6 +3192,9 @@ + bus-width = <4>; + dma-coherent; + ++ /* Forbid SDR104/SDR50 - broken hw! */ ++ sdhci-caps-mask = <0x3 0x0>; ++ + status = "disabled"; + + sdhc2_opp_table: opp-table { +diff --git a/arch/arm64/boot/dts/renesas/r8a779f0.dtsi b/arch/arm64/boot/dts/renesas/r8a779f0.dtsi +index c2f152bcf10ec..4092c0016035e 100644 +--- a/arch/arm64/boot/dts/renesas/r8a779f0.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a779f0.dtsi +@@ -577,7 +577,7 @@ + reg = <0 0xe6540000 0 0x60>; + interrupts = <GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 514>, +- <&cpg CPG_CORE R8A779F0_CLK_S0D3>, ++ <&cpg CPG_CORE R8A779F0_CLK_SASYNCPERD1>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac0 0x31>, <&dmac0 0x30>, +@@ -594,7 +594,7 @@ + reg = <0 0xe6550000 0 0x60>; + interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 515>, +- <&cpg CPG_CORE R8A779F0_CLK_S0D3>, ++ <&cpg CPG_CORE R8A779F0_CLK_SASYNCPERD1>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac0 0x33>, <&dmac0 0x32>, +@@ -611,7 +611,7 @@ + reg = <0 0xe6560000 0 0x60>; + interrupts = <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 516>, +- <&cpg CPG_CORE R8A779F0_CLK_S0D3>, ++ <&cpg CPG_CORE R8A779F0_CLK_SASYNCPERD1>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac0 0x35>, <&dmac0 0x34>, +@@ -628,7 +628,7 @@ + reg = <0 0xe66a0000 0 0x60>; + interrupts = <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 517>, +- <&cpg CPG_CORE R8A779F0_CLK_S0D3>, ++ <&cpg CPG_CORE R8A779F0_CLK_SASYNCPERD1>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac0 0x37>, <&dmac0 0x36>, +@@ -657,7 +657,7 @@ + reg = <0 0xe6e60000 0 64>; + interrupts = <GIC_SPI 249 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 702>, +- <&cpg CPG_CORE R8A779F0_CLK_S0D3_PER>, ++ <&cpg CPG_CORE R8A779F0_CLK_SASYNCPERD1>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac0 0x51>, <&dmac0 0x50>, +@@ -674,7 +674,7 @@ + reg = <0 0xe6e68000 0 64>; + interrupts = <GIC_SPI 250 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 703>, +- <&cpg CPG_CORE R8A779F0_CLK_S0D3_PER>, ++ <&cpg CPG_CORE R8A779F0_CLK_SASYNCPERD1>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac0 0x53>, <&dmac0 0x52>, +@@ -691,7 +691,7 @@ + reg = <0 0xe6c50000 0 64>; + interrupts = <GIC_SPI 252 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 704>, +- <&cpg CPG_CORE R8A779F0_CLK_S0D3_PER>, ++ <&cpg CPG_CORE R8A779F0_CLK_SASYNCPERD1>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac0 0x57>, <&dmac0 0x56>, +@@ -708,7 +708,7 @@ + reg = <0 0xe6c40000 0 64>; + interrupts = <GIC_SPI 253 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 705>, +- <&cpg CPG_CORE R8A779F0_CLK_S0D3_PER>, ++ <&cpg CPG_CORE R8A779F0_CLK_SASYNCPERD1>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac0 0x59>, <&dmac0 0x58>, +diff --git a/arch/arm64/boot/dts/renesas/r8a779g0.dtsi b/arch/arm64/boot/dts/renesas/r8a779g0.dtsi +index d70f0600ae5a9..d58b18802cb01 100644 +--- a/arch/arm64/boot/dts/renesas/r8a779g0.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a779g0.dtsi +@@ -326,7 +326,7 @@ + reg = <0 0xe6540000 0 96>; + interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 514>, +- <&cpg CPG_CORE R8A779G0_CLK_S0D3_PER>, ++ <&cpg CPG_CORE R8A779G0_CLK_SASYNCPERD1>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>; +diff --git a/arch/arm64/boot/dts/renesas/r9a09g011.dtsi b/arch/arm64/boot/dts/renesas/r9a09g011.dtsi +index fb1a97202c387..ebaa8cdd747d2 100644 +--- a/arch/arm64/boot/dts/renesas/r9a09g011.dtsi ++++ b/arch/arm64/boot/dts/renesas/r9a09g011.dtsi +@@ -48,7 +48,7 @@ + #size-cells = <2>; + ranges; + +- gic: interrupt-controller@82000000 { ++ gic: interrupt-controller@82010000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + #address-cells = <0>; +@@ -126,7 +126,7 @@ + i2c0: i2c@a4030000 { + #address-cells = <1>; + #size-cells = <0>; +- compatible = "renesas,i2c-r9a09g011", "renesas,rzv2m-i2c"; ++ compatible = "renesas,r9a09g011-i2c", "renesas,rzv2m-i2c"; + reg = <0 0xa4030000 0 0x80>; + interrupts = <GIC_SPI 232 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 236 IRQ_TYPE_EDGE_RISING>; +@@ -140,7 +140,7 @@ + i2c2: i2c@a4030100 { + #address-cells = <1>; + #size-cells = <0>; +- compatible = "renesas,i2c-r9a09g011", "renesas,rzv2m-i2c"; ++ compatible = "renesas,r9a09g011-i2c", "renesas,rzv2m-i2c"; + reg = <0 0xa4030100 0 0x80>; + interrupts = <GIC_SPI 234 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 238 IRQ_TYPE_EDGE_RISING>; +diff --git a/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi b/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi +index d0abb9aa0e9ed..e3852c9463528 100644 +--- a/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi ++++ b/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi +@@ -55,14 +55,14 @@ + samsung,pins = "gpf5-0"; + samsung,pin-function = <FSD_PIN_FUNC_2>; + samsung,pin-pud = <FSD_PIN_PULL_NONE>; +- samsung,pin-drv = <FSD_PIN_DRV_LV2>; ++ samsung,pin-drv = <FSD_PIN_DRV_LV4>; + }; + + ufs_refclk_out: ufs-refclk-out-pins { + samsung,pins = "gpf5-1"; + samsung,pin-function = <FSD_PIN_FUNC_2>; + samsung,pin-pud = <FSD_PIN_PULL_NONE>; +- samsung,pin-drv = <FSD_PIN_DRV_LV2>; ++ samsung,pin-drv = <FSD_PIN_DRV_LV4>; + }; + }; + +@@ -239,105 +239,105 @@ + samsung,pins = "gpb6-1"; + samsung,pin-function = <FSD_PIN_FUNC_2>; + samsung,pin-pud = <FSD_PIN_PULL_UP>; +- samsung,pin-drv = <FSD_PIN_DRV_LV2>; ++ samsung,pin-drv = <FSD_PIN_DRV_LV4>; + }; + + pwm1_out: pwm1-out-pins { + samsung,pins = "gpb6-5"; + samsung,pin-function = <FSD_PIN_FUNC_2>; + samsung,pin-pud = <FSD_PIN_PULL_UP>; +- samsung,pin-drv = <FSD_PIN_DRV_LV2>; ++ samsung,pin-drv = <FSD_PIN_DRV_LV4>; + }; + + hs_i2c0_bus: hs-i2c0-bus-pins { + samsung,pins = "gpb0-0", "gpb0-1"; + samsung,pin-function = <FSD_PIN_FUNC_2>; + samsung,pin-pud = <FSD_PIN_PULL_UP>; +- samsung,pin-drv = <FSD_PIN_DRV_LV1>; ++ samsung,pin-drv = <FSD_PIN_DRV_LV4>; + }; + + hs_i2c1_bus: hs-i2c1-bus-pins { + samsung,pins = "gpb0-2", "gpb0-3"; + samsung,pin-function = <FSD_PIN_FUNC_2>; + samsung,pin-pud = <FSD_PIN_PULL_UP>; +- samsung,pin-drv = <FSD_PIN_DRV_LV1>; ++ samsung,pin-drv = <FSD_PIN_DRV_LV4>; + }; + + hs_i2c2_bus: hs-i2c2-bus-pins { + samsung,pins = "gpb0-4", "gpb0-5"; + samsung,pin-function = <FSD_PIN_FUNC_2>; + samsung,pin-pud = <FSD_PIN_PULL_UP>; +- samsung,pin-drv = <FSD_PIN_DRV_LV1>; ++ samsung,pin-drv = <FSD_PIN_DRV_LV4>; + }; + + hs_i2c3_bus: hs-i2c3-bus-pins { + samsung,pins = "gpb0-6", "gpb0-7"; + samsung,pin-function = <FSD_PIN_FUNC_2>; + samsung,pin-pud = <FSD_PIN_PULL_UP>; +- samsung,pin-drv = <FSD_PIN_DRV_LV1>; ++ samsung,pin-drv = <FSD_PIN_DRV_LV4>; + }; + + hs_i2c4_bus: hs-i2c4-bus-pins { + samsung,pins = "gpb1-0", "gpb1-1"; + samsung,pin-function = <FSD_PIN_FUNC_2>; + samsung,pin-pud = <FSD_PIN_PULL_UP>; +- samsung,pin-drv = <FSD_PIN_DRV_LV1>; ++ samsung,pin-drv = <FSD_PIN_DRV_LV4>; + }; + + hs_i2c5_bus: hs-i2c5-bus-pins { + samsung,pins = "gpb1-2", "gpb1-3"; + samsung,pin-function = <FSD_PIN_FUNC_2>; + samsung,pin-pud = <FSD_PIN_PULL_UP>; +- samsung,pin-drv = <FSD_PIN_DRV_LV1>; ++ samsung,pin-drv = <FSD_PIN_DRV_LV4>; + }; + + hs_i2c6_bus: hs-i2c6-bus-pins { + samsung,pins = "gpb1-4", "gpb1-5"; + samsung,pin-function = <FSD_PIN_FUNC_2>; + samsung,pin-pud = <FSD_PIN_PULL_UP>; +- samsung,pin-drv = <FSD_PIN_DRV_LV1>; ++ samsung,pin-drv = <FSD_PIN_DRV_LV4>; + }; + + hs_i2c7_bus: hs-i2c7-bus-pins { + samsung,pins = "gpb1-6", "gpb1-7"; + samsung,pin-function = <FSD_PIN_FUNC_2>; + samsung,pin-pud = <FSD_PIN_PULL_UP>; +- samsung,pin-drv = <FSD_PIN_DRV_LV1>; ++ samsung,pin-drv = <FSD_PIN_DRV_LV4>; + }; + + uart0_data: uart0-data-pins { + samsung,pins = "gpb7-0", "gpb7-1"; + samsung,pin-function = <FSD_PIN_FUNC_2>; + samsung,pin-pud = <FSD_PIN_PULL_NONE>; +- samsung,pin-drv = <FSD_PIN_DRV_LV1>; ++ samsung,pin-drv = <FSD_PIN_DRV_LV4>; + }; + + uart1_data: uart1-data-pins { + samsung,pins = "gpb7-4", "gpb7-5"; + samsung,pin-function = <FSD_PIN_FUNC_2>; + samsung,pin-pud = <FSD_PIN_PULL_NONE>; +- samsung,pin-drv = <FSD_PIN_DRV_LV1>; ++ samsung,pin-drv = <FSD_PIN_DRV_LV4>; + }; + + spi0_bus: spi0-bus-pins { + samsung,pins = "gpb4-0", "gpb4-2", "gpb4-3"; + samsung,pin-function = <FSD_PIN_FUNC_2>; + samsung,pin-pud = <FSD_PIN_PULL_UP>; +- samsung,pin-drv = <FSD_PIN_DRV_LV1>; ++ samsung,pin-drv = <FSD_PIN_DRV_LV4>; + }; + + spi1_bus: spi1-bus-pins { + samsung,pins = "gpb4-4", "gpb4-6", "gpb4-7"; + samsung,pin-function = <FSD_PIN_FUNC_2>; + samsung,pin-pud = <FSD_PIN_PULL_UP>; +- samsung,pin-drv = <FSD_PIN_DRV_LV1>; ++ samsung,pin-drv = <FSD_PIN_DRV_LV4>; + }; + + spi2_bus: spi2-bus-pins { + samsung,pins = "gpb5-0", "gpb5-2", "gpb5-3"; + samsung,pin-function = <FSD_PIN_FUNC_2>; + samsung,pin-pud = <FSD_PIN_PULL_UP>; +- samsung,pin-drv = <FSD_PIN_DRV_LV1>; ++ samsung,pin-drv = <FSD_PIN_DRV_LV4>; + }; + }; + +diff --git a/arch/arm64/boot/dts/tesla/fsd-pinctrl.h b/arch/arm64/boot/dts/tesla/fsd-pinctrl.h +index 6ffbda3624930..c397d02208a08 100644 +--- a/arch/arm64/boot/dts/tesla/fsd-pinctrl.h ++++ b/arch/arm64/boot/dts/tesla/fsd-pinctrl.h +@@ -16,9 +16,9 @@ + #define FSD_PIN_PULL_UP 3 + + #define FSD_PIN_DRV_LV1 0 +-#define FSD_PIN_DRV_LV2 2 +-#define FSD_PIN_DRV_LV3 1 +-#define FSD_PIN_DRV_LV4 3 ++#define FSD_PIN_DRV_LV2 1 ++#define FSD_PIN_DRV_LV4 2 ++#define FSD_PIN_DRV_LV6 3 + + #define FSD_PIN_FUNC_INPUT 0 + #define FSD_PIN_FUNC_OUTPUT 1 +diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi +index 4005a73cfea99..ebb1c5ce7aece 100644 +--- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi +@@ -120,7 +120,6 @@ + dmas = <&main_udmap 0xc001>, <&main_udmap 0x4002>, + <&main_udmap 0x4003>; + dma-names = "tx", "rx1", "rx2"; +- dma-coherent; + + rng: rng@4e10000 { + compatible = "inside-secure,safexcel-eip76"; +diff --git a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi +index e5be78a58682d..d3fb86b2ea939 100644 +--- a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi +@@ -386,7 +386,6 @@ + dmas = <&mcu_udmap 0xf501>, <&mcu_udmap 0x7502>, + <&mcu_udmap 0x7503>; + dma-names = "tx", "rx1", "rx2"; +- dma-coherent; + + rng: rng@40910000 { + compatible = "inside-secure,safexcel-eip76"; +diff --git a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi +index 917c9dc99efaa..603ddda5127fa 100644 +--- a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi +@@ -337,7 +337,6 @@ + dmas = <&main_udmap 0xc000>, <&main_udmap 0x4000>, + <&main_udmap 0x4001>; + dma-names = "tx", "rx1", "rx2"; +- dma-coherent; + + rng: rng@4e10000 { + compatible = "inside-secure,safexcel-eip76"; +diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi +index 34e7d577ae13b..c89f28235812a 100644 +--- a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi +@@ -60,7 +60,7 @@ + #interrupt-cells = <1>; + ti,sci = <&sms>; + ti,sci-dev-id = <148>; +- ti,interrupt-ranges = <8 360 56>; ++ ti,interrupt-ranges = <8 392 56>; + }; + + main_pmx0: pinctrl@11c000 { +diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi +index 4d1bfabd1313a..f0644851602cd 100644 +--- a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi +@@ -65,7 +65,7 @@ + #interrupt-cells = <1>; + ti,sci = <&sms>; + ti,sci-dev-id = <125>; +- ti,interrupt-ranges = <16 928 16>; ++ ti,interrupt-ranges = <16 960 16>; + }; + + mcu_conf: syscon@40f00000 { +diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig +index 8bd80508a710d..4b121dc0cfba2 100644 +--- a/arch/arm64/crypto/Kconfig ++++ b/arch/arm64/crypto/Kconfig +@@ -96,6 +96,17 @@ config CRYPTO_SHA3_ARM64 + Architecture: arm64 using: + - ARMv8.2 Crypto Extensions + ++config CRYPTO_SM3_NEON ++ tristate "Hash functions: SM3 (NEON)" ++ depends on KERNEL_MODE_NEON ++ select CRYPTO_HASH ++ select CRYPTO_SM3 ++ help ++ SM3 (ShangMi 3) secure hash function (OSCCA GM/T 0004-2012) ++ ++ Architecture: arm64 using: ++ - NEON (Advanced SIMD) extensions ++ + config CRYPTO_SM3_ARM64_CE + tristate "Hash functions: SM3 (ARMv8.2 Crypto Extensions)" + depends on KERNEL_MODE_NEON +diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile +index 24bb0c4610de2..087f1625e7751 100644 +--- a/arch/arm64/crypto/Makefile ++++ b/arch/arm64/crypto/Makefile +@@ -17,6 +17,9 @@ sha512-ce-y := sha512-ce-glue.o sha512-ce-core.o + obj-$(CONFIG_CRYPTO_SHA3_ARM64) += sha3-ce.o + sha3-ce-y := sha3-ce-glue.o sha3-ce-core.o + ++obj-$(CONFIG_CRYPTO_SM3_NEON) += sm3-neon.o ++sm3-neon-y := sm3-neon-glue.o sm3-neon-core.o ++ + obj-$(CONFIG_CRYPTO_SM3_ARM64_CE) += sm3-ce.o + sm3-ce-y := sm3-ce-glue.o sm3-ce-core.o + +diff --git a/arch/arm64/crypto/sm3-neon-core.S b/arch/arm64/crypto/sm3-neon-core.S +new file mode 100644 +index 0000000000000..4357e0e51be38 +--- /dev/null ++++ b/arch/arm64/crypto/sm3-neon-core.S +@@ -0,0 +1,601 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * sm3-neon-core.S - SM3 secure hash using NEON instructions ++ * ++ * Linux/arm64 port of the libgcrypt SM3 implementation for AArch64 ++ * ++ * Copyright (C) 2021 Jussi Kivilinna <jussi.kivilinna@iki.fi> ++ * Copyright (c) 2022 Tianjia Zhang <tianjia.zhang@linux.alibaba.com> ++ */ ++ ++#include <linux/linkage.h> ++#include <linux/cfi_types.h> ++#include <asm/assembler.h> ++ ++/* Context structure */ ++ ++#define state_h0 0 ++#define state_h1 4 ++#define state_h2 8 ++#define state_h3 12 ++#define state_h4 16 ++#define state_h5 20 ++#define state_h6 24 ++#define state_h7 28 ++ ++/* Stack structure */ ++ ++#define STACK_W_SIZE (32 * 2 * 3) ++ ++#define STACK_W (0) ++#define STACK_SIZE (STACK_W + STACK_W_SIZE) ++ ++/* Register macros */ ++ ++#define RSTATE x0 ++#define RDATA x1 ++#define RNBLKS x2 ++#define RKPTR x28 ++#define RFRAME x29 ++ ++#define ra w3 ++#define rb w4 ++#define rc w5 ++#define rd w6 ++#define re w7 ++#define rf w8 ++#define rg w9 ++#define rh w10 ++ ++#define t0 w11 ++#define t1 w12 ++#define t2 w13 ++#define t3 w14 ++#define t4 w15 ++#define t5 w16 ++#define t6 w17 ++ ++#define k_even w19 ++#define k_odd w20 ++ ++#define addr0 x21 ++#define addr1 x22 ++ ++#define s0 w23 ++#define s1 w24 ++#define s2 w25 ++#define s3 w26 ++ ++#define W0 v0 ++#define W1 v1 ++#define W2 v2 ++#define W3 v3 ++#define W4 v4 ++#define W5 v5 ++ ++#define XTMP0 v6 ++#define XTMP1 v7 ++#define XTMP2 v16 ++#define XTMP3 v17 ++#define XTMP4 v18 ++#define XTMP5 v19 ++#define XTMP6 v20 ++ ++/* Helper macros. */ ++ ++#define _(...) /*_*/ ++ ++#define clear_vec(x) \ ++ movi x.8h, #0; ++ ++#define rolw(o, a, n) \ ++ ror o, a, #(32 - n); ++ ++/* Round function macros. */ ++ ++#define GG1_1(x, y, z, o, t) \ ++ eor o, x, y; ++#define GG1_2(x, y, z, o, t) \ ++ eor o, o, z; ++#define GG1_3(x, y, z, o, t) ++ ++#define FF1_1(x, y, z, o, t) GG1_1(x, y, z, o, t) ++#define FF1_2(x, y, z, o, t) ++#define FF1_3(x, y, z, o, t) GG1_2(x, y, z, o, t) ++ ++#define GG2_1(x, y, z, o, t) \ ++ bic o, z, x; ++#define GG2_2(x, y, z, o, t) \ ++ and t, y, x; ++#define GG2_3(x, y, z, o, t) \ ++ eor o, o, t; ++ ++#define FF2_1(x, y, z, o, t) \ ++ eor o, x, y; ++#define FF2_2(x, y, z, o, t) \ ++ and t, x, y; \ ++ and o, o, z; ++#define FF2_3(x, y, z, o, t) \ ++ eor o, o, t; ++ ++#define R(i, a, b, c, d, e, f, g, h, k, K_LOAD, round, widx, wtype, IOP, iop_param) \ ++ K_LOAD(round); \ ++ ldr t5, [sp, #(wtype##_W1_ADDR(round, widx))]; \ ++ rolw(t0, a, 12); /* rol(a, 12) => t0 */ \ ++ IOP(1, iop_param); \ ++ FF##i##_1(a, b, c, t1, t2); \ ++ ldr t6, [sp, #(wtype##_W1W2_ADDR(round, widx))]; \ ++ add k, k, e; \ ++ IOP(2, iop_param); \ ++ GG##i##_1(e, f, g, t3, t4); \ ++ FF##i##_2(a, b, c, t1, t2); \ ++ IOP(3, iop_param); \ ++ add k, k, t0; \ ++ add h, h, t5; \ ++ add d, d, t6; /* w1w2 + d => d */ \ ++ IOP(4, iop_param); \ ++ rolw(k, k, 7); /* rol (t0 + e + t), 7) => k */ \ ++ GG##i##_2(e, f, g, t3, t4); \ ++ add h, h, k; /* h + w1 + k => h */ \ ++ IOP(5, iop_param); \ ++ FF##i##_3(a, b, c, t1, t2); \ ++ eor t0, t0, k; /* k ^ t0 => t0 */ \ ++ GG##i##_3(e, f, g, t3, t4); \ ++ add d, d, t1; /* FF(a,b,c) + d => d */ \ ++ IOP(6, iop_param); \ ++ add t3, t3, h; /* GG(e,f,g) + h => t3 */ \ ++ rolw(b, b, 9); /* rol(b, 9) => b */ \ ++ eor h, t3, t3, ror #(32-9); \ ++ IOP(7, iop_param); \ ++ add d, d, t0; /* t0 + d => d */ \ ++ rolw(f, f, 19); /* rol(f, 19) => f */ \ ++ IOP(8, iop_param); \ ++ eor h, h, t3, ror #(32-17); /* P0(t3) => h */ ++ ++#define R1(a, b, c, d, e, f, g, h, k, K_LOAD, round, widx, wtype, IOP, iop_param) \ ++ R(1, ##a, ##b, ##c, ##d, ##e, ##f, ##g, ##h, ##k, K_LOAD, round, widx, wtype, IOP, iop_param) ++ ++#define R2(a, b, c, d, e, f, g, h, k, K_LOAD, round, widx, wtype, IOP, iop_param) \ ++ R(2, ##a, ##b, ##c, ##d, ##e, ##f, ##g, ##h, ##k, K_LOAD, round, widx, wtype, IOP, iop_param) ++ ++#define KL(round) \ ++ ldp k_even, k_odd, [RKPTR, #(4*(round))]; ++ ++/* Input expansion macros. */ ++ ++/* Byte-swapped input address. */ ++#define IW_W_ADDR(round, widx, offs) \ ++ (STACK_W + ((round) / 4) * 64 + (offs) + ((widx) * 4)) ++ ++/* Expanded input address. */ ++#define XW_W_ADDR(round, widx, offs) \ ++ (STACK_W + ((((round) / 3) - 4) % 2) * 64 + (offs) + ((widx) * 4)) ++ ++/* Rounds 1-12, byte-swapped input block addresses. */ ++#define IW_W1_ADDR(round, widx) IW_W_ADDR(round, widx, 32) ++#define IW_W1W2_ADDR(round, widx) IW_W_ADDR(round, widx, 48) ++ ++/* Rounds 1-12, expanded input block addresses. */ ++#define XW_W1_ADDR(round, widx) XW_W_ADDR(round, widx, 0) ++#define XW_W1W2_ADDR(round, widx) XW_W_ADDR(round, widx, 16) ++ ++/* Input block loading. ++ * Interleaving within round function needed for in-order CPUs. */ ++#define LOAD_W_VEC_1_1() \ ++ add addr0, sp, #IW_W1_ADDR(0, 0); ++#define LOAD_W_VEC_1_2() \ ++ add addr1, sp, #IW_W1_ADDR(4, 0); ++#define LOAD_W_VEC_1_3() \ ++ ld1 {W0.16b}, [RDATA], #16; ++#define LOAD_W_VEC_1_4() \ ++ ld1 {W1.16b}, [RDATA], #16; ++#define LOAD_W_VEC_1_5() \ ++ ld1 {W2.16b}, [RDATA], #16; ++#define LOAD_W_VEC_1_6() \ ++ ld1 {W3.16b}, [RDATA], #16; ++#define LOAD_W_VEC_1_7() \ ++ rev32 XTMP0.16b, W0.16b; ++#define LOAD_W_VEC_1_8() \ ++ rev32 XTMP1.16b, W1.16b; ++#define LOAD_W_VEC_2_1() \ ++ rev32 XTMP2.16b, W2.16b; ++#define LOAD_W_VEC_2_2() \ ++ rev32 XTMP3.16b, W3.16b; ++#define LOAD_W_VEC_2_3() \ ++ eor XTMP4.16b, XTMP1.16b, XTMP0.16b; ++#define LOAD_W_VEC_2_4() \ ++ eor XTMP5.16b, XTMP2.16b, XTMP1.16b; ++#define LOAD_W_VEC_2_5() \ ++ st1 {XTMP0.16b}, [addr0], #16; ++#define LOAD_W_VEC_2_6() \ ++ st1 {XTMP4.16b}, [addr0]; \ ++ add addr0, sp, #IW_W1_ADDR(8, 0); ++#define LOAD_W_VEC_2_7() \ ++ eor XTMP6.16b, XTMP3.16b, XTMP2.16b; ++#define LOAD_W_VEC_2_8() \ ++ ext W0.16b, XTMP0.16b, XTMP0.16b, #8; /* W0: xx, w0, xx, xx */ ++#define LOAD_W_VEC_3_1() \ ++ mov W2.16b, XTMP1.16b; /* W2: xx, w6, w5, w4 */ ++#define LOAD_W_VEC_3_2() \ ++ st1 {XTMP1.16b}, [addr1], #16; ++#define LOAD_W_VEC_3_3() \ ++ st1 {XTMP5.16b}, [addr1]; \ ++ ext W1.16b, XTMP0.16b, XTMP0.16b, #4; /* W1: xx, w3, w2, w1 */ ++#define LOAD_W_VEC_3_4() \ ++ ext W3.16b, XTMP1.16b, XTMP2.16b, #12; /* W3: xx, w9, w8, w7 */ ++#define LOAD_W_VEC_3_5() \ ++ ext W4.16b, XTMP2.16b, XTMP3.16b, #8; /* W4: xx, w12, w11, w10 */ ++#define LOAD_W_VEC_3_6() \ ++ st1 {XTMP2.16b}, [addr0], #16; ++#define LOAD_W_VEC_3_7() \ ++ st1 {XTMP6.16b}, [addr0]; ++#define LOAD_W_VEC_3_8() \ ++ ext W5.16b, XTMP3.16b, XTMP3.16b, #4; /* W5: xx, w15, w14, w13 */ ++ ++#define LOAD_W_VEC_1(iop_num, ...) \ ++ LOAD_W_VEC_1_##iop_num() ++#define LOAD_W_VEC_2(iop_num, ...) \ ++ LOAD_W_VEC_2_##iop_num() ++#define LOAD_W_VEC_3(iop_num, ...) \ ++ LOAD_W_VEC_3_##iop_num() ++ ++/* Message scheduling. Note: 3 words per vector register. ++ * Interleaving within round function needed for in-order CPUs. */ ++#define SCHED_W_1_1(round, w0, w1, w2, w3, w4, w5) \ ++ /* Load (w[i - 16]) => XTMP0 */ \ ++ /* Load (w[i - 13]) => XTMP5 */ \ ++ ext XTMP0.16b, w0.16b, w0.16b, #12; /* XTMP0: w0, xx, xx, xx */ ++#define SCHED_W_1_2(round, w0, w1, w2, w3, w4, w5) \ ++ ext XTMP5.16b, w1.16b, w1.16b, #12; ++#define SCHED_W_1_3(round, w0, w1, w2, w3, w4, w5) \ ++ ext XTMP0.16b, XTMP0.16b, w1.16b, #12; /* XTMP0: xx, w2, w1, w0 */ ++#define SCHED_W_1_4(round, w0, w1, w2, w3, w4, w5) \ ++ ext XTMP5.16b, XTMP5.16b, w2.16b, #12; ++#define SCHED_W_1_5(round, w0, w1, w2, w3, w4, w5) \ ++ /* w[i - 9] == w3 */ \ ++ /* W3 ^ XTMP0 => XTMP0 */ \ ++ eor XTMP0.16b, XTMP0.16b, w3.16b; ++#define SCHED_W_1_6(round, w0, w1, w2, w3, w4, w5) \ ++ /* w[i - 3] == w5 */ \ ++ /* rol(XMM5, 15) ^ XTMP0 => XTMP0 */ \ ++ /* rol(XTMP5, 7) => XTMP1 */ \ ++ add addr0, sp, #XW_W1_ADDR((round), 0); \ ++ shl XTMP2.4s, w5.4s, #15; ++#define SCHED_W_1_7(round, w0, w1, w2, w3, w4, w5) \ ++ shl XTMP1.4s, XTMP5.4s, #7; ++#define SCHED_W_1_8(round, w0, w1, w2, w3, w4, w5) \ ++ sri XTMP2.4s, w5.4s, #(32-15); ++#define SCHED_W_2_1(round, w0, w1, w2, w3, w4, w5) \ ++ sri XTMP1.4s, XTMP5.4s, #(32-7); ++#define SCHED_W_2_2(round, w0, w1, w2, w3, w4, w5) \ ++ eor XTMP0.16b, XTMP0.16b, XTMP2.16b; ++#define SCHED_W_2_3(round, w0, w1, w2, w3, w4, w5) \ ++ /* w[i - 6] == W4 */ \ ++ /* W4 ^ XTMP1 => XTMP1 */ \ ++ eor XTMP1.16b, XTMP1.16b, w4.16b; ++#define SCHED_W_2_4(round, w0, w1, w2, w3, w4, w5) \ ++ /* P1(XTMP0) ^ XTMP1 => W0 */ \ ++ shl XTMP3.4s, XTMP0.4s, #15; ++#define SCHED_W_2_5(round, w0, w1, w2, w3, w4, w5) \ ++ shl XTMP4.4s, XTMP0.4s, #23; ++#define SCHED_W_2_6(round, w0, w1, w2, w3, w4, w5) \ ++ eor w0.16b, XTMP1.16b, XTMP0.16b; ++#define SCHED_W_2_7(round, w0, w1, w2, w3, w4, w5) \ ++ sri XTMP3.4s, XTMP0.4s, #(32-15); ++#define SCHED_W_2_8(round, w0, w1, w2, w3, w4, w5) \ ++ sri XTMP4.4s, XTMP0.4s, #(32-23); ++#define SCHED_W_3_1(round, w0, w1, w2, w3, w4, w5) \ ++ eor w0.16b, w0.16b, XTMP3.16b; ++#define SCHED_W_3_2(round, w0, w1, w2, w3, w4, w5) \ ++ /* Load (w[i - 3]) => XTMP2 */ \ ++ ext XTMP2.16b, w4.16b, w4.16b, #12; ++#define SCHED_W_3_3(round, w0, w1, w2, w3, w4, w5) \ ++ eor w0.16b, w0.16b, XTMP4.16b; ++#define SCHED_W_3_4(round, w0, w1, w2, w3, w4, w5) \ ++ ext XTMP2.16b, XTMP2.16b, w5.16b, #12; ++#define SCHED_W_3_5(round, w0, w1, w2, w3, w4, w5) \ ++ /* W1 ^ W2 => XTMP3 */ \ ++ eor XTMP3.16b, XTMP2.16b, w0.16b; ++#define SCHED_W_3_6(round, w0, w1, w2, w3, w4, w5) ++#define SCHED_W_3_7(round, w0, w1, w2, w3, w4, w5) \ ++ st1 {XTMP2.16b-XTMP3.16b}, [addr0]; ++#define SCHED_W_3_8(round, w0, w1, w2, w3, w4, w5) ++ ++#define SCHED_W_W0W1W2W3W4W5_1(iop_num, round) \ ++ SCHED_W_1_##iop_num(round, W0, W1, W2, W3, W4, W5) ++#define SCHED_W_W0W1W2W3W4W5_2(iop_num, round) \ ++ SCHED_W_2_##iop_num(round, W0, W1, W2, W3, W4, W5) ++#define SCHED_W_W0W1W2W3W4W5_3(iop_num, round) \ ++ SCHED_W_3_##iop_num(round, W0, W1, W2, W3, W4, W5) ++ ++#define SCHED_W_W1W2W3W4W5W0_1(iop_num, round) \ ++ SCHED_W_1_##iop_num(round, W1, W2, W3, W4, W5, W0) ++#define SCHED_W_W1W2W3W4W5W0_2(iop_num, round) \ ++ SCHED_W_2_##iop_num(round, W1, W2, W3, W4, W5, W0) ++#define SCHED_W_W1W2W3W4W5W0_3(iop_num, round) \ ++ SCHED_W_3_##iop_num(round, W1, W2, W3, W4, W5, W0) ++ ++#define SCHED_W_W2W3W4W5W0W1_1(iop_num, round) \ ++ SCHED_W_1_##iop_num(round, W2, W3, W4, W5, W0, W1) ++#define SCHED_W_W2W3W4W5W0W1_2(iop_num, round) \ ++ SCHED_W_2_##iop_num(round, W2, W3, W4, W5, W0, W1) ++#define SCHED_W_W2W3W4W5W0W1_3(iop_num, round) \ ++ SCHED_W_3_##iop_num(round, W2, W3, W4, W5, W0, W1) ++ ++#define SCHED_W_W3W4W5W0W1W2_1(iop_num, round) \ ++ SCHED_W_1_##iop_num(round, W3, W4, W5, W0, W1, W2) ++#define SCHED_W_W3W4W5W0W1W2_2(iop_num, round) \ ++ SCHED_W_2_##iop_num(round, W3, W4, W5, W0, W1, W2) ++#define SCHED_W_W3W4W5W0W1W2_3(iop_num, round) \ ++ SCHED_W_3_##iop_num(round, W3, W4, W5, W0, W1, W2) ++ ++#define SCHED_W_W4W5W0W1W2W3_1(iop_num, round) \ ++ SCHED_W_1_##iop_num(round, W4, W5, W0, W1, W2, W3) ++#define SCHED_W_W4W5W0W1W2W3_2(iop_num, round) \ ++ SCHED_W_2_##iop_num(round, W4, W5, W0, W1, W2, W3) ++#define SCHED_W_W4W5W0W1W2W3_3(iop_num, round) \ ++ SCHED_W_3_##iop_num(round, W4, W5, W0, W1, W2, W3) ++ ++#define SCHED_W_W5W0W1W2W3W4_1(iop_num, round) \ ++ SCHED_W_1_##iop_num(round, W5, W0, W1, W2, W3, W4) ++#define SCHED_W_W5W0W1W2W3W4_2(iop_num, round) \ ++ SCHED_W_2_##iop_num(round, W5, W0, W1, W2, W3, W4) ++#define SCHED_W_W5W0W1W2W3W4_3(iop_num, round) \ ++ SCHED_W_3_##iop_num(round, W5, W0, W1, W2, W3, W4) ++ ++ ++ /* ++ * Transform blocks*64 bytes (blocks*16 32-bit words) at 'src'. ++ * ++ * void sm3_neon_transform(struct sm3_state *sst, u8 const *src, ++ * int blocks) ++ */ ++ .text ++.align 3 ++SYM_TYPED_FUNC_START(sm3_neon_transform) ++ ldp ra, rb, [RSTATE, #0] ++ ldp rc, rd, [RSTATE, #8] ++ ldp re, rf, [RSTATE, #16] ++ ldp rg, rh, [RSTATE, #24] ++ ++ stp x28, x29, [sp, #-16]! ++ stp x19, x20, [sp, #-16]! ++ stp x21, x22, [sp, #-16]! ++ stp x23, x24, [sp, #-16]! ++ stp x25, x26, [sp, #-16]! ++ mov RFRAME, sp ++ ++ sub addr0, sp, #STACK_SIZE ++ adr_l RKPTR, .LKtable ++ and sp, addr0, #(~63) ++ ++ /* Preload first block. */ ++ LOAD_W_VEC_1(1, 0) ++ LOAD_W_VEC_1(2, 0) ++ LOAD_W_VEC_1(3, 0) ++ LOAD_W_VEC_1(4, 0) ++ LOAD_W_VEC_1(5, 0) ++ LOAD_W_VEC_1(6, 0) ++ LOAD_W_VEC_1(7, 0) ++ LOAD_W_VEC_1(8, 0) ++ LOAD_W_VEC_2(1, 0) ++ LOAD_W_VEC_2(2, 0) ++ LOAD_W_VEC_2(3, 0) ++ LOAD_W_VEC_2(4, 0) ++ LOAD_W_VEC_2(5, 0) ++ LOAD_W_VEC_2(6, 0) ++ LOAD_W_VEC_2(7, 0) ++ LOAD_W_VEC_2(8, 0) ++ LOAD_W_VEC_3(1, 0) ++ LOAD_W_VEC_3(2, 0) ++ LOAD_W_VEC_3(3, 0) ++ LOAD_W_VEC_3(4, 0) ++ LOAD_W_VEC_3(5, 0) ++ LOAD_W_VEC_3(6, 0) ++ LOAD_W_VEC_3(7, 0) ++ LOAD_W_VEC_3(8, 0) ++ ++.balign 16 ++.Loop: ++ /* Transform 0-3 */ ++ R1(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 0, 0, IW, _, 0) ++ R1(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 1, 1, IW, _, 0) ++ R1(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 2, 2, IW, _, 0) ++ R1(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 3, 3, IW, _, 0) ++ ++ /* Transform 4-7 + Precalc 12-14 */ ++ R1(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 4, 0, IW, _, 0) ++ R1(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 5, 1, IW, _, 0) ++ R1(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 6, 2, IW, SCHED_W_W0W1W2W3W4W5_1, 12) ++ R1(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 7, 3, IW, SCHED_W_W0W1W2W3W4W5_2, 12) ++ ++ /* Transform 8-11 + Precalc 12-17 */ ++ R1(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 8, 0, IW, SCHED_W_W0W1W2W3W4W5_3, 12) ++ R1(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 9, 1, IW, SCHED_W_W1W2W3W4W5W0_1, 15) ++ R1(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 10, 2, IW, SCHED_W_W1W2W3W4W5W0_2, 15) ++ R1(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 11, 3, IW, SCHED_W_W1W2W3W4W5W0_3, 15) ++ ++ /* Transform 12-14 + Precalc 18-20 */ ++ R1(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 12, 0, XW, SCHED_W_W2W3W4W5W0W1_1, 18) ++ R1(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 13, 1, XW, SCHED_W_W2W3W4W5W0W1_2, 18) ++ R1(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 14, 2, XW, SCHED_W_W2W3W4W5W0W1_3, 18) ++ ++ /* Transform 15-17 + Precalc 21-23 */ ++ R1(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 15, 0, XW, SCHED_W_W3W4W5W0W1W2_1, 21) ++ R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 16, 1, XW, SCHED_W_W3W4W5W0W1W2_2, 21) ++ R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 17, 2, XW, SCHED_W_W3W4W5W0W1W2_3, 21) ++ ++ /* Transform 18-20 + Precalc 24-26 */ ++ R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 18, 0, XW, SCHED_W_W4W5W0W1W2W3_1, 24) ++ R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 19, 1, XW, SCHED_W_W4W5W0W1W2W3_2, 24) ++ R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 20, 2, XW, SCHED_W_W4W5W0W1W2W3_3, 24) ++ ++ /* Transform 21-23 + Precalc 27-29 */ ++ R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 21, 0, XW, SCHED_W_W5W0W1W2W3W4_1, 27) ++ R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 22, 1, XW, SCHED_W_W5W0W1W2W3W4_2, 27) ++ R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 23, 2, XW, SCHED_W_W5W0W1W2W3W4_3, 27) ++ ++ /* Transform 24-26 + Precalc 30-32 */ ++ R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 24, 0, XW, SCHED_W_W0W1W2W3W4W5_1, 30) ++ R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 25, 1, XW, SCHED_W_W0W1W2W3W4W5_2, 30) ++ R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 26, 2, XW, SCHED_W_W0W1W2W3W4W5_3, 30) ++ ++ /* Transform 27-29 + Precalc 33-35 */ ++ R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 27, 0, XW, SCHED_W_W1W2W3W4W5W0_1, 33) ++ R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 28, 1, XW, SCHED_W_W1W2W3W4W5W0_2, 33) ++ R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 29, 2, XW, SCHED_W_W1W2W3W4W5W0_3, 33) ++ ++ /* Transform 30-32 + Precalc 36-38 */ ++ R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 30, 0, XW, SCHED_W_W2W3W4W5W0W1_1, 36) ++ R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 31, 1, XW, SCHED_W_W2W3W4W5W0W1_2, 36) ++ R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 32, 2, XW, SCHED_W_W2W3W4W5W0W1_3, 36) ++ ++ /* Transform 33-35 + Precalc 39-41 */ ++ R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 33, 0, XW, SCHED_W_W3W4W5W0W1W2_1, 39) ++ R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 34, 1, XW, SCHED_W_W3W4W5W0W1W2_2, 39) ++ R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 35, 2, XW, SCHED_W_W3W4W5W0W1W2_3, 39) ++ ++ /* Transform 36-38 + Precalc 42-44 */ ++ R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 36, 0, XW, SCHED_W_W4W5W0W1W2W3_1, 42) ++ R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 37, 1, XW, SCHED_W_W4W5W0W1W2W3_2, 42) ++ R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 38, 2, XW, SCHED_W_W4W5W0W1W2W3_3, 42) ++ ++ /* Transform 39-41 + Precalc 45-47 */ ++ R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 39, 0, XW, SCHED_W_W5W0W1W2W3W4_1, 45) ++ R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 40, 1, XW, SCHED_W_W5W0W1W2W3W4_2, 45) ++ R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 41, 2, XW, SCHED_W_W5W0W1W2W3W4_3, 45) ++ ++ /* Transform 42-44 + Precalc 48-50 */ ++ R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 42, 0, XW, SCHED_W_W0W1W2W3W4W5_1, 48) ++ R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 43, 1, XW, SCHED_W_W0W1W2W3W4W5_2, 48) ++ R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 44, 2, XW, SCHED_W_W0W1W2W3W4W5_3, 48) ++ ++ /* Transform 45-47 + Precalc 51-53 */ ++ R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 45, 0, XW, SCHED_W_W1W2W3W4W5W0_1, 51) ++ R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 46, 1, XW, SCHED_W_W1W2W3W4W5W0_2, 51) ++ R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 47, 2, XW, SCHED_W_W1W2W3W4W5W0_3, 51) ++ ++ /* Transform 48-50 + Precalc 54-56 */ ++ R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 48, 0, XW, SCHED_W_W2W3W4W5W0W1_1, 54) ++ R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 49, 1, XW, SCHED_W_W2W3W4W5W0W1_2, 54) ++ R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 50, 2, XW, SCHED_W_W2W3W4W5W0W1_3, 54) ++ ++ /* Transform 51-53 + Precalc 57-59 */ ++ R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 51, 0, XW, SCHED_W_W3W4W5W0W1W2_1, 57) ++ R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 52, 1, XW, SCHED_W_W3W4W5W0W1W2_2, 57) ++ R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 53, 2, XW, SCHED_W_W3W4W5W0W1W2_3, 57) ++ ++ /* Transform 54-56 + Precalc 60-62 */ ++ R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 54, 0, XW, SCHED_W_W4W5W0W1W2W3_1, 60) ++ R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 55, 1, XW, SCHED_W_W4W5W0W1W2W3_2, 60) ++ R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 56, 2, XW, SCHED_W_W4W5W0W1W2W3_3, 60) ++ ++ /* Transform 57-59 + Precalc 63 */ ++ R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 57, 0, XW, SCHED_W_W5W0W1W2W3W4_1, 63) ++ R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 58, 1, XW, SCHED_W_W5W0W1W2W3W4_2, 63) ++ R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 59, 2, XW, SCHED_W_W5W0W1W2W3W4_3, 63) ++ ++ /* Transform 60 */ ++ R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 60, 0, XW, _, _) ++ subs RNBLKS, RNBLKS, #1 ++ b.eq .Lend ++ ++ /* Transform 61-63 + Preload next block */ ++ R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 61, 1, XW, LOAD_W_VEC_1, _) ++ ldp s0, s1, [RSTATE, #0] ++ R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 62, 2, XW, LOAD_W_VEC_2, _) ++ ldp s2, s3, [RSTATE, #8] ++ R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 63, 0, XW, LOAD_W_VEC_3, _) ++ ++ /* Update the chaining variables. */ ++ eor ra, ra, s0 ++ eor rb, rb, s1 ++ ldp s0, s1, [RSTATE, #16] ++ eor rc, rc, s2 ++ ldp k_even, k_odd, [RSTATE, #24] ++ eor rd, rd, s3 ++ eor re, re, s0 ++ stp ra, rb, [RSTATE, #0] ++ eor rf, rf, s1 ++ stp rc, rd, [RSTATE, #8] ++ eor rg, rg, k_even ++ stp re, rf, [RSTATE, #16] ++ eor rh, rh, k_odd ++ stp rg, rh, [RSTATE, #24] ++ b .Loop ++ ++.Lend: ++ /* Transform 61-63 */ ++ R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 61, 1, XW, _, _) ++ ldp s0, s1, [RSTATE, #0] ++ R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 62, 2, XW, _, _) ++ ldp s2, s3, [RSTATE, #8] ++ R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 63, 0, XW, _, _) ++ ++ /* Update the chaining variables. */ ++ eor ra, ra, s0 ++ clear_vec(W0) ++ eor rb, rb, s1 ++ clear_vec(W1) ++ ldp s0, s1, [RSTATE, #16] ++ clear_vec(W2) ++ eor rc, rc, s2 ++ clear_vec(W3) ++ ldp k_even, k_odd, [RSTATE, #24] ++ clear_vec(W4) ++ eor rd, rd, s3 ++ clear_vec(W5) ++ eor re, re, s0 ++ clear_vec(XTMP0) ++ stp ra, rb, [RSTATE, #0] ++ clear_vec(XTMP1) ++ eor rf, rf, s1 ++ clear_vec(XTMP2) ++ stp rc, rd, [RSTATE, #8] ++ clear_vec(XTMP3) ++ eor rg, rg, k_even ++ clear_vec(XTMP4) ++ stp re, rf, [RSTATE, #16] ++ clear_vec(XTMP5) ++ eor rh, rh, k_odd ++ clear_vec(XTMP6) ++ stp rg, rh, [RSTATE, #24] ++ ++ /* Clear message expansion area */ ++ add addr0, sp, #STACK_W ++ st1 {W0.16b-W3.16b}, [addr0], #64 ++ st1 {W0.16b-W3.16b}, [addr0], #64 ++ st1 {W0.16b-W3.16b}, [addr0] ++ ++ mov sp, RFRAME ++ ++ ldp x25, x26, [sp], #16 ++ ldp x23, x24, [sp], #16 ++ ldp x21, x22, [sp], #16 ++ ldp x19, x20, [sp], #16 ++ ldp x28, x29, [sp], #16 ++ ++ ret ++SYM_FUNC_END(sm3_neon_transform) ++ ++ ++ .section ".rodata", "a" ++ ++ .align 4 ++.LKtable: ++ .long 0x79cc4519, 0xf3988a32, 0xe7311465, 0xce6228cb ++ .long 0x9cc45197, 0x3988a32f, 0x7311465e, 0xe6228cbc ++ .long 0xcc451979, 0x988a32f3, 0x311465e7, 0x6228cbce ++ .long 0xc451979c, 0x88a32f39, 0x11465e73, 0x228cbce6 ++ .long 0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c ++ .long 0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce ++ .long 0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec ++ .long 0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5 ++ .long 0x7a879d8a, 0xf50f3b14, 0xea1e7629, 0xd43cec53 ++ .long 0xa879d8a7, 0x50f3b14f, 0xa1e7629e, 0x43cec53d ++ .long 0x879d8a7a, 0x0f3b14f5, 0x1e7629ea, 0x3cec53d4 ++ .long 0x79d8a7a8, 0xf3b14f50, 0xe7629ea1, 0xcec53d43 ++ .long 0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c ++ .long 0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce ++ .long 0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec ++ .long 0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5 +diff --git a/arch/arm64/crypto/sm3-neon-glue.c b/arch/arm64/crypto/sm3-neon-glue.c +new file mode 100644 +index 0000000000000..7182ee683f14a +--- /dev/null ++++ b/arch/arm64/crypto/sm3-neon-glue.c +@@ -0,0 +1,103 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * sm3-neon-glue.c - SM3 secure hash using NEON instructions ++ * ++ * Copyright (C) 2022 Tianjia Zhang <tianjia.zhang@linux.alibaba.com> ++ */ ++ ++#include <asm/neon.h> ++#include <asm/simd.h> ++#include <asm/unaligned.h> ++#include <crypto/internal/hash.h> ++#include <crypto/internal/simd.h> ++#include <crypto/sm3.h> ++#include <crypto/sm3_base.h> ++#include <linux/cpufeature.h> ++#include <linux/crypto.h> ++#include <linux/module.h> ++ ++ ++asmlinkage void sm3_neon_transform(struct sm3_state *sst, u8 const *src, ++ int blocks); ++ ++static int sm3_neon_update(struct shash_desc *desc, const u8 *data, ++ unsigned int len) ++{ ++ if (!crypto_simd_usable()) { ++ sm3_update(shash_desc_ctx(desc), data, len); ++ return 0; ++ } ++ ++ kernel_neon_begin(); ++ sm3_base_do_update(desc, data, len, sm3_neon_transform); ++ kernel_neon_end(); ++ ++ return 0; ++} ++ ++static int sm3_neon_final(struct shash_desc *desc, u8 *out) ++{ ++ if (!crypto_simd_usable()) { ++ sm3_final(shash_desc_ctx(desc), out); ++ return 0; ++ } ++ ++ kernel_neon_begin(); ++ sm3_base_do_finalize(desc, sm3_neon_transform); ++ kernel_neon_end(); ++ ++ return sm3_base_finish(desc, out); ++} ++ ++static int sm3_neon_finup(struct shash_desc *desc, const u8 *data, ++ unsigned int len, u8 *out) ++{ ++ if (!crypto_simd_usable()) { ++ struct sm3_state *sctx = shash_desc_ctx(desc); ++ ++ if (len) ++ sm3_update(sctx, data, len); ++ sm3_final(sctx, out); ++ return 0; ++ } ++ ++ kernel_neon_begin(); ++ if (len) ++ sm3_base_do_update(desc, data, len, sm3_neon_transform); ++ sm3_base_do_finalize(desc, sm3_neon_transform); ++ kernel_neon_end(); ++ ++ return sm3_base_finish(desc, out); ++} ++ ++static struct shash_alg sm3_alg = { ++ .digestsize = SM3_DIGEST_SIZE, ++ .init = sm3_base_init, ++ .update = sm3_neon_update, ++ .final = sm3_neon_final, ++ .finup = sm3_neon_finup, ++ .descsize = sizeof(struct sm3_state), ++ .base.cra_name = "sm3", ++ .base.cra_driver_name = "sm3-neon", ++ .base.cra_blocksize = SM3_BLOCK_SIZE, ++ .base.cra_module = THIS_MODULE, ++ .base.cra_priority = 200, ++}; ++ ++static int __init sm3_neon_init(void) ++{ ++ return crypto_register_shash(&sm3_alg); ++} ++ ++static void __exit sm3_neon_fini(void) ++{ ++ crypto_unregister_shash(&sm3_alg); ++} ++ ++module_init(sm3_neon_init); ++module_exit(sm3_neon_fini); ++ ++MODULE_DESCRIPTION("SM3 secure hash using NEON instructions"); ++MODULE_AUTHOR("Jussi Kivilinna <jussi.kivilinna@iki.fi>"); ++MODULE_AUTHOR("Tianjia Zhang <tianjia.zhang@linux.alibaba.com>"); ++MODULE_LICENSE("GPL v2"); +diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h +index 445aa3af3b762..400f8956328b9 100644 +--- a/arch/arm64/include/asm/processor.h ++++ b/arch/arm64/include/asm/processor.h +@@ -308,13 +308,13 @@ static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc, + } + #endif + +-static inline bool is_ttbr0_addr(unsigned long addr) ++static __always_inline bool is_ttbr0_addr(unsigned long addr) + { + /* entry assembly clears tags for TTBR0 addrs */ + return addr < TASK_SIZE; + } + +-static inline bool is_ttbr1_addr(unsigned long addr) ++static __always_inline bool is_ttbr1_addr(unsigned long addr) + { + /* TTBR1 addresses may have a tag if KASAN_SW_TAGS is in use */ + return arch_kasan_reset_tag(addr) >= PAGE_OFFSET; +diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c +index 5b391490e045b..74f76514a48d0 100644 +--- a/arch/arm64/mm/fault.c ++++ b/arch/arm64/mm/fault.c +@@ -353,6 +353,11 @@ static bool is_el1_mte_sync_tag_check_fault(unsigned long esr) + return false; + } + ++static bool is_translation_fault(unsigned long esr) ++{ ++ return (esr & ESR_ELx_FSC_TYPE) == ESR_ELx_FSC_FAULT; ++} ++ + static void __do_kernel_fault(unsigned long addr, unsigned long esr, + struct pt_regs *regs) + { +@@ -385,7 +390,8 @@ static void __do_kernel_fault(unsigned long addr, unsigned long esr, + } else if (addr < PAGE_SIZE) { + msg = "NULL pointer dereference"; + } else { +- if (kfence_handle_page_fault(addr, esr & ESR_ELx_WNR, regs)) ++ if (is_translation_fault(esr) && ++ kfence_handle_page_fault(addr, esr & ESR_ELx_WNR, regs)) + return; + + msg = "paging request"; +diff --git a/arch/mips/bcm63xx/clk.c b/arch/mips/bcm63xx/clk.c +index 6e6756e8fa0a9..86a6e25908664 100644 +--- a/arch/mips/bcm63xx/clk.c ++++ b/arch/mips/bcm63xx/clk.c +@@ -361,6 +361,8 @@ static struct clk clk_periph = { + */ + int clk_enable(struct clk *clk) + { ++ if (!clk) ++ return 0; + mutex_lock(&clocks_mutex); + clk_enable_unlocked(clk); + mutex_unlock(&clocks_mutex); +diff --git a/arch/mips/boot/dts/ingenic/ci20.dts b/arch/mips/boot/dts/ingenic/ci20.dts +index 37c46720c719a..f38c39572a9e8 100644 +--- a/arch/mips/boot/dts/ingenic/ci20.dts ++++ b/arch/mips/boot/dts/ingenic/ci20.dts +@@ -438,7 +438,7 @@ + ingenic,nemc-tAW = <50>; + ingenic,nemc-tSTRV = <100>; + +- reset-gpios = <&gpf 12 GPIO_ACTIVE_HIGH>; ++ reset-gpios = <&gpf 12 GPIO_ACTIVE_LOW>; + vcc-supply = <ð0_power>; + + interrupt-parent = <&gpe>; +diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c +index d09d0769f5496..0fd9ac76eb742 100644 +--- a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c ++++ b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c +@@ -211,7 +211,7 @@ union cvmx_helper_link_info __cvmx_helper_board_link_get(int ipd_port) + { + union cvmx_helper_link_info result; + +- WARN(!octeon_is_simulation(), ++ WARN_ONCE(!octeon_is_simulation(), + "Using deprecated link status - please update your DT"); + + /* Unless we fix it later, all links are defaulted to down */ +diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper.c b/arch/mips/cavium-octeon/executive/cvmx-helper.c +index 6f49fd9be1f3c..9abfc4bf9bd83 100644 +--- a/arch/mips/cavium-octeon/executive/cvmx-helper.c ++++ b/arch/mips/cavium-octeon/executive/cvmx-helper.c +@@ -1096,7 +1096,7 @@ union cvmx_helper_link_info cvmx_helper_link_get(int ipd_port) + if (index == 0) + result = __cvmx_helper_rgmii_link_get(ipd_port); + else { +- WARN(1, "Using deprecated link status - please update your DT"); ++ WARN_ONCE(1, "Using deprecated link status - please update your DT"); + result.s.full_duplex = 1; + result.s.link_up = 1; + result.s.speed = 1000; +diff --git a/arch/mips/include/asm/mach-ralink/mt7621.h b/arch/mips/include/asm/mach-ralink/mt7621.h +index 6bbf082dd149e..79d5bb0e06d63 100644 +--- a/arch/mips/include/asm/mach-ralink/mt7621.h ++++ b/arch/mips/include/asm/mach-ralink/mt7621.h +@@ -7,10 +7,12 @@ + #ifndef _MT7621_REGS_H_ + #define _MT7621_REGS_H_ + ++#define IOMEM(x) ((void __iomem *)(KSEG1ADDR(x))) ++ + #define MT7621_PALMBUS_BASE 0x1C000000 + #define MT7621_PALMBUS_SIZE 0x03FFFFFF + +-#define MT7621_SYSC_BASE 0x1E000000 ++#define MT7621_SYSC_BASE IOMEM(0x1E000000) + + #define SYSC_REG_CHIP_NAME0 0x00 + #define SYSC_REG_CHIP_NAME1 0x04 +diff --git a/arch/mips/kernel/vpe-cmp.c b/arch/mips/kernel/vpe-cmp.c +index e673603e11e5d..92140edb3ce3e 100644 +--- a/arch/mips/kernel/vpe-cmp.c ++++ b/arch/mips/kernel/vpe-cmp.c +@@ -75,7 +75,6 @@ ATTRIBUTE_GROUPS(vpe); + + static void vpe_device_release(struct device *cd) + { +- kfree(cd); + } + + static struct class vpe_class = { +@@ -157,6 +156,7 @@ out_dev: + device_del(&vpe_device); + + out_class: ++ put_device(&vpe_device); + class_unregister(&vpe_class); + + out_chrdev: +@@ -169,7 +169,7 @@ void __exit vpe_module_exit(void) + { + struct vpe *v, *n; + +- device_del(&vpe_device); ++ device_unregister(&vpe_device); + class_unregister(&vpe_class); + unregister_chrdev(major, VPE_MODULE_NAME); + +diff --git a/arch/mips/kernel/vpe-mt.c b/arch/mips/kernel/vpe-mt.c +index bad6b0891b2b5..84a82b551ec35 100644 +--- a/arch/mips/kernel/vpe-mt.c ++++ b/arch/mips/kernel/vpe-mt.c +@@ -313,7 +313,6 @@ ATTRIBUTE_GROUPS(vpe); + + static void vpe_device_release(struct device *cd) + { +- kfree(cd); + } + + static struct class vpe_class = { +@@ -497,6 +496,7 @@ out_dev: + device_del(&vpe_device); + + out_class: ++ put_device(&vpe_device); + class_unregister(&vpe_class); + + out_chrdev: +@@ -509,7 +509,7 @@ void __exit vpe_module_exit(void) + { + struct vpe *v, *n; + +- device_del(&vpe_device); ++ device_unregister(&vpe_device); + class_unregister(&vpe_class); + unregister_chrdev(major, VPE_MODULE_NAME); + +diff --git a/arch/mips/ralink/mt7621.c b/arch/mips/ralink/mt7621.c +index fb0565bc34fda..bbf5811afbf2c 100644 +--- a/arch/mips/ralink/mt7621.c ++++ b/arch/mips/ralink/mt7621.c +@@ -25,6 +25,7 @@ + #define MT7621_MEM_TEST_PATTERN 0xaa5555aa + + static u32 detect_magic __initdata; ++static struct ralink_soc_info *soc_info_ptr; + + int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) + { +@@ -97,41 +98,83 @@ void __init ralink_of_remap(void) + panic("Failed to remap core resources"); + } + +-static void soc_dev_init(struct ralink_soc_info *soc_info, u32 rev) ++static unsigned int __init mt7621_get_soc_name0(void) ++{ ++ return __raw_readl(MT7621_SYSC_BASE + SYSC_REG_CHIP_NAME0); ++} ++ ++static unsigned int __init mt7621_get_soc_name1(void) ++{ ++ return __raw_readl(MT7621_SYSC_BASE + SYSC_REG_CHIP_NAME1); ++} ++ ++static bool __init mt7621_soc_valid(void) ++{ ++ if (mt7621_get_soc_name0() == MT7621_CHIP_NAME0 && ++ mt7621_get_soc_name1() == MT7621_CHIP_NAME1) ++ return true; ++ else ++ return false; ++} ++ ++static const char __init *mt7621_get_soc_id(void) ++{ ++ if (mt7621_soc_valid()) ++ return "MT7621"; ++ else ++ return "invalid"; ++} ++ ++static unsigned int __init mt7621_get_soc_rev(void) ++{ ++ return __raw_readl(MT7621_SYSC_BASE + SYSC_REG_CHIP_REV); ++} ++ ++static unsigned int __init mt7621_get_soc_ver(void) ++{ ++ return (mt7621_get_soc_rev() >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK; ++} ++ ++static unsigned int __init mt7621_get_soc_eco(void) ++{ ++ return (mt7621_get_soc_rev() & CHIP_REV_ECO_MASK); ++} ++ ++static const char __init *mt7621_get_soc_revision(void) ++{ ++ if (mt7621_get_soc_rev() == 1 && mt7621_get_soc_eco() == 1) ++ return "E2"; ++ else ++ return "E1"; ++} ++ ++static int __init mt7621_soc_dev_init(void) + { + struct soc_device *soc_dev; + struct soc_device_attribute *soc_dev_attr; + + soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); + if (!soc_dev_attr) +- return; ++ return -ENOMEM; + + soc_dev_attr->soc_id = "mt7621"; + soc_dev_attr->family = "Ralink"; ++ soc_dev_attr->revision = mt7621_get_soc_revision(); + +- if (((rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK) == 1 && +- (rev & CHIP_REV_ECO_MASK) == 1) +- soc_dev_attr->revision = "E2"; +- else +- soc_dev_attr->revision = "E1"; +- +- soc_dev_attr->data = soc_info; ++ soc_dev_attr->data = soc_info_ptr; + + soc_dev = soc_device_register(soc_dev_attr); + if (IS_ERR(soc_dev)) { + kfree(soc_dev_attr); +- return; ++ return PTR_ERR(soc_dev); + } ++ ++ return 0; + } ++device_initcall(mt7621_soc_dev_init); + + void __init prom_soc_init(struct ralink_soc_info *soc_info) + { +- void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7621_SYSC_BASE); +- unsigned char *name = NULL; +- u32 n0; +- u32 n1; +- u32 rev; +- + /* Early detection of CMP support */ + mips_cm_probe(); + mips_cpc_probe(); +@@ -154,27 +197,23 @@ void __init prom_soc_init(struct ralink_soc_info *soc_info) + __sync(); + } + +- n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0); +- n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1); +- +- if (n0 == MT7621_CHIP_NAME0 && n1 == MT7621_CHIP_NAME1) { +- name = "MT7621"; ++ if (mt7621_soc_valid()) + soc_info->compatible = "mediatek,mt7621-soc"; +- } else { +- panic("mt7621: unknown SoC, n0:%08x n1:%08x\n", n0, n1); +- } ++ else ++ panic("mt7621: unknown SoC, n0:%08x n1:%08x\n", ++ mt7621_get_soc_name0(), ++ mt7621_get_soc_name1()); + ralink_soc = MT762X_SOC_MT7621AT; +- rev = __raw_readl(sysc + SYSC_REG_CHIP_REV); + + snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, + "MediaTek %s ver:%u eco:%u", +- name, +- (rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK, +- (rev & CHIP_REV_ECO_MASK)); ++ mt7621_get_soc_id(), ++ mt7621_get_soc_ver(), ++ mt7621_get_soc_eco()); + + soc_info->mem_detect = mt7621_memory_detect; + +- soc_dev_init(soc_info, rev); ++ soc_info_ptr = soc_info; + + if (!register_cps_smp_ops()) + return; +diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c +index ea8072acf8d94..01c132bc33d54 100644 +--- a/arch/mips/ralink/of.c ++++ b/arch/mips/ralink/of.c +@@ -21,6 +21,7 @@ + #include <asm/bootinfo.h> + #include <asm/addrspace.h> + #include <asm/prom.h> ++#include <asm/mach-ralink/ralink_regs.h> + + #include "common.h" + +@@ -81,7 +82,8 @@ static int __init plat_of_setup(void) + __dt_register_buses(soc_info.compatible, "palmbus"); + + /* make sure that the reset controller is setup early */ +- ralink_rst_init(); ++ if (ralink_soc != MT762X_SOC_MT7621AT) ++ ralink_rst_init(); + + return 0; + } +diff --git a/arch/powerpc/boot/dts/turris1x.dts b/arch/powerpc/boot/dts/turris1x.dts +index 045af668e9284..e9cda34a140e0 100644 +--- a/arch/powerpc/boot/dts/turris1x.dts ++++ b/arch/powerpc/boot/dts/turris1x.dts +@@ -69,6 +69,20 @@ + interrupt-parent = <&gpio>; + interrupts = <12 IRQ_TYPE_LEVEL_LOW>, /* GPIO12 - ALERT pin */ + <13 IRQ_TYPE_LEVEL_LOW>; /* GPIO13 - CRIT pin */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* Local temperature sensor (SA56004ED internal) */ ++ channel@0 { ++ reg = <0>; ++ label = "board"; ++ }; ++ ++ /* Remote temperature sensor (D+/D- connected to P2020 CPU Temperature Diode) */ ++ channel@1 { ++ reg = <1>; ++ label = "cpu"; ++ }; + }; + + /* DDR3 SPD/EEPROM */ +diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h +index 8abae463f6c12..95fd7f9485d55 100644 +--- a/arch/powerpc/include/asm/hvcall.h ++++ b/arch/powerpc/include/asm/hvcall.h +@@ -79,7 +79,7 @@ + #define H_NOT_ENOUGH_RESOURCES -44 + #define H_R_STATE -45 + #define H_RESCINDED -46 +-#define H_P1 -54 ++#define H_ABORTED -54 + #define H_P2 -55 + #define H_P3 -56 + #define H_P4 -57 +@@ -100,7 +100,6 @@ + #define H_COP_HW -74 + #define H_STATE -75 + #define H_IN_USE -77 +-#define H_ABORTED -78 + #define H_UNSUPPORTED_FLAG_START -256 + #define H_UNSUPPORTED_FLAG_END -511 + #define H_MULTI_THREADS_ACTIVE -9005 +diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c +index e847f9b1c5b9f..767ab166933ba 100644 +--- a/arch/powerpc/kernel/rtas.c ++++ b/arch/powerpc/kernel/rtas.c +@@ -889,6 +889,7 @@ void __noreturn rtas_halt(void) + + /* Must be in the RMO region, so we place it here */ + static char rtas_os_term_buf[2048]; ++static s32 ibm_os_term_token = RTAS_UNKNOWN_SERVICE; + + void rtas_os_term(char *str) + { +@@ -900,16 +901,20 @@ void rtas_os_term(char *str) + * this property may terminate the partition which we want to avoid + * since it interferes with panic_timeout. + */ +- if (RTAS_UNKNOWN_SERVICE == rtas_token("ibm,os-term") || +- RTAS_UNKNOWN_SERVICE == rtas_token("ibm,extended-os-term")) ++ if (ibm_os_term_token == RTAS_UNKNOWN_SERVICE) + return; + + snprintf(rtas_os_term_buf, 2048, "OS panic: %s", str); + ++ /* ++ * Keep calling as long as RTAS returns a "try again" status, ++ * but don't use rtas_busy_delay(), which potentially ++ * schedules. ++ */ + do { +- status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL, ++ status = rtas_call(ibm_os_term_token, 1, 1, NULL, + __pa(rtas_os_term_buf)); +- } while (rtas_busy_delay(status)); ++ } while (rtas_busy_delay_time(status)); + + if (status != 0) + printk(KERN_EMERG "ibm,os-term call failed %d\n", status); +@@ -1277,6 +1282,13 @@ void __init rtas_initialize(void) + no_entry = of_property_read_u32(rtas.dev, "linux,rtas-entry", &entry); + rtas.entry = no_entry ? rtas.base : entry; + ++ /* ++ * Discover these now to avoid device tree lookups in the ++ * panic path. ++ */ ++ if (of_property_read_bool(rtas.dev, "ibm,extended-os-term")) ++ ibm_os_term_token = rtas_token("ibm,os-term"); ++ + /* If RTAS was found, allocate the RMO buffer for it and look for + * the stop-self token if any + */ +diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c +index 082f6d0308a47..8718289c051dd 100644 +--- a/arch/powerpc/perf/callchain.c ++++ b/arch/powerpc/perf/callchain.c +@@ -61,6 +61,7 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re + next_sp = fp[0]; + + if (next_sp == sp + STACK_INT_FRAME_SIZE && ++ validate_sp(sp, current, STACK_INT_FRAME_SIZE) && + fp[STACK_FRAME_MARKER] == STACK_FRAME_REGS_MARKER) { + /* + * This looks like an interrupt frame for an +diff --git a/arch/powerpc/perf/hv-gpci-requests.h b/arch/powerpc/perf/hv-gpci-requests.h +index 8965b4463d433..5e86371a20c78 100644 +--- a/arch/powerpc/perf/hv-gpci-requests.h ++++ b/arch/powerpc/perf/hv-gpci-requests.h +@@ -79,6 +79,7 @@ REQUEST(__field(0, 8, partition_id) + ) + #include I(REQUEST_END) + ++#ifdef ENABLE_EVENTS_COUNTERINFO_V6 + /* + * Not available for counter_info_version >= 0x8, use + * run_instruction_cycles_by_partition(0x100) instead. +@@ -92,6 +93,7 @@ REQUEST(__field(0, 8, partition_id) + __count(0x10, 8, cycles) + ) + #include I(REQUEST_END) ++#endif + + #define REQUEST_NAME system_performance_capabilities + #define REQUEST_NUM 0x40 +@@ -103,6 +105,7 @@ REQUEST(__field(0, 1, perf_collect_privileged) + ) + #include I(REQUEST_END) + ++#ifdef ENABLE_EVENTS_COUNTERINFO_V6 + #define REQUEST_NAME processor_bus_utilization_abc_links + #define REQUEST_NUM 0x50 + #define REQUEST_IDX_KIND "hw_chip_id=?" +@@ -194,6 +197,7 @@ REQUEST(__field(0, 4, phys_processor_idx) + __count(0x28, 8, instructions_completed) + ) + #include I(REQUEST_END) ++#endif + + /* Processor_core_power_mode (0x95) skipped, no counters */ + /* Affinity_domain_information_by_virtual_processor (0xA0) skipped, +diff --git a/arch/powerpc/perf/hv-gpci.c b/arch/powerpc/perf/hv-gpci.c +index 5eb60ed5b5e8a..7ff8ff3509f5f 100644 +--- a/arch/powerpc/perf/hv-gpci.c ++++ b/arch/powerpc/perf/hv-gpci.c +@@ -70,9 +70,9 @@ static const struct attribute_group format_group = { + .attrs = format_attrs, + }; + +-static const struct attribute_group event_group = { ++static struct attribute_group event_group = { + .name = "events", +- .attrs = hv_gpci_event_attrs, ++ /* .attrs is set in init */ + }; + + #define HV_CAPS_ATTR(_name, _format) \ +@@ -330,6 +330,7 @@ static int hv_gpci_init(void) + int r; + unsigned long hret; + struct hv_perf_caps caps; ++ struct hv_gpci_request_buffer *arg; + + hv_gpci_assert_offsets_correct(); + +@@ -353,6 +354,36 @@ static int hv_gpci_init(void) + /* sampling not supported */ + h_gpci_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT; + ++ arg = (void *)get_cpu_var(hv_gpci_reqb); ++ memset(arg, 0, HGPCI_REQ_BUFFER_SIZE); ++ ++ /* ++ * hcall H_GET_PERF_COUNTER_INFO populates the output ++ * counter_info_version value based on the system hypervisor. ++ * Pass the counter request 0x10 corresponds to request type ++ * 'Dispatch_timebase_by_processor', to get the supported ++ * counter_info_version. ++ */ ++ arg->params.counter_request = cpu_to_be32(0x10); ++ ++ r = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO, ++ virt_to_phys(arg), HGPCI_REQ_BUFFER_SIZE); ++ if (r) { ++ pr_devel("hcall failed, can't get supported counter_info_version: 0x%x\n", r); ++ arg->params.counter_info_version_out = 0x8; ++ } ++ ++ /* ++ * Use counter_info_version_out value to assign ++ * required hv-gpci event list. ++ */ ++ if (arg->params.counter_info_version_out >= 0x8) ++ event_group.attrs = hv_gpci_event_attrs; ++ else ++ event_group.attrs = hv_gpci_event_attrs_v6; ++ ++ put_cpu_var(hv_gpci_reqb); ++ + r = perf_pmu_register(&h_gpci_pmu, h_gpci_pmu.name, -1); + if (r) + return r; +diff --git a/arch/powerpc/perf/hv-gpci.h b/arch/powerpc/perf/hv-gpci.h +index 4d108262bed79..c72020912dea5 100644 +--- a/arch/powerpc/perf/hv-gpci.h ++++ b/arch/powerpc/perf/hv-gpci.h +@@ -26,6 +26,7 @@ enum { + #define REQUEST_FILE "../hv-gpci-requests.h" + #define NAME_LOWER hv_gpci + #define NAME_UPPER HV_GPCI ++#define ENABLE_EVENTS_COUNTERINFO_V6 + #include "req-gen/perf.h" + #undef REQUEST_FILE + #undef NAME_LOWER +diff --git a/arch/powerpc/perf/req-gen/perf.h b/arch/powerpc/perf/req-gen/perf.h +index fa9bc804e67af..6b2a59fefffa7 100644 +--- a/arch/powerpc/perf/req-gen/perf.h ++++ b/arch/powerpc/perf/req-gen/perf.h +@@ -139,6 +139,26 @@ PMU_EVENT_ATTR_STRING( \ + #define REQUEST_(r_name, r_value, r_idx_1, r_fields) \ + r_fields + ++/* Generate event list for platforms with counter_info_version 0x6 or below */ ++static __maybe_unused struct attribute *hv_gpci_event_attrs_v6[] = { ++#include REQUEST_FILE ++ NULL ++}; ++ ++/* ++ * Based on getPerfCountInfo v1.018 documentation, some of the hv-gpci ++ * events were deprecated for platform firmware that supports ++ * counter_info_version 0x8 or above. ++ * Those deprecated events are still part of platform firmware that ++ * support counter_info_version 0x6 and below. As per the getPerfCountInfo ++ * v1.018 documentation there is no counter_info_version 0x7. ++ * Undefining macro ENABLE_EVENTS_COUNTERINFO_V6, to disable the addition of ++ * deprecated events in "hv_gpci_event_attrs" attribute group, for platforms ++ * that supports counter_info_version 0x8 or above. ++ */ ++#undef ENABLE_EVENTS_COUNTERINFO_V6 ++ ++/* Generate event list for platforms with counter_info_version 0x8 or above*/ + static __maybe_unused struct attribute *hv_gpci_event_attrs[] = { + #include REQUEST_FILE + NULL +diff --git a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c +index 48038aaedbd36..2875c206ac0f8 100644 +--- a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c ++++ b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c +@@ -531,6 +531,7 @@ static int mpc52xx_lpbfifo_probe(struct platform_device *op) + err_bcom_rx_irq: + bcom_gen_bd_rx_release(lpbfifo.bcom_rx_task); + err_bcom_rx: ++ free_irq(lpbfifo.irq, &lpbfifo); + err_irq: + iounmap(lpbfifo.regs); + lpbfifo.regs = NULL; +diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c +index e12cb44e717f1..caa96edf0e72a 100644 +--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c ++++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c +@@ -107,7 +107,7 @@ static int __init of_fsl_spi_probe(char *type, char *compatible, u32 sysclk, + + goto next; + unreg: +- platform_device_del(pdev); ++ platform_device_put(pdev); + err: + pr_err("%pOF: registration failed\n", np); + next: +diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c +index 8e40ccac0f44e..e5a58a9b2fe9f 100644 +--- a/arch/powerpc/platforms/pseries/eeh_pseries.c ++++ b/arch/powerpc/platforms/pseries/eeh_pseries.c +@@ -848,16 +848,7 @@ static int __init eeh_pseries_init(void) + } + + /* Initialize error log size */ +- eeh_error_buf_size = rtas_token("rtas-error-log-max"); +- if (eeh_error_buf_size == RTAS_UNKNOWN_SERVICE) { +- pr_info("%s: unknown EEH error log size\n", +- __func__); +- eeh_error_buf_size = 1024; +- } else if (eeh_error_buf_size > RTAS_ERROR_LOG_MAX) { +- pr_info("%s: EEH error log size %d exceeds the maximal %d\n", +- __func__, eeh_error_buf_size, RTAS_ERROR_LOG_MAX); +- eeh_error_buf_size = RTAS_ERROR_LOG_MAX; +- } ++ eeh_error_buf_size = rtas_get_error_log_max(); + + /* Set EEH probe mode */ + eeh_add_flag(EEH_PROBE_MODE_DEVTREE | EEH_ENABLE_IO_FOR_LOG); +diff --git a/arch/powerpc/platforms/pseries/plpks.c b/arch/powerpc/platforms/pseries/plpks.c +index f4b5b5a64db3d..63a1e1fe01851 100644 +--- a/arch/powerpc/platforms/pseries/plpks.c ++++ b/arch/powerpc/platforms/pseries/plpks.c +@@ -75,7 +75,7 @@ static int pseries_status_to_err(int rc) + case H_FUNCTION: + err = -ENXIO; + break; +- case H_P1: ++ case H_PARAMETER: + case H_P2: + case H_P3: + case H_P4: +@@ -111,7 +111,7 @@ static int pseries_status_to_err(int rc) + err = -EEXIST; + break; + case H_ABORTED: +- err = -EINTR; ++ err = -EIO; + break; + default: + err = -EINVAL; +@@ -366,22 +366,24 @@ static int plpks_read_var(u8 consumer, struct plpks_var *var) + { + unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 }; + struct plpks_auth *auth; +- struct label *label; ++ struct label *label = NULL; + u8 *output; + int rc; + + if (var->namelen > MAX_NAME_SIZE) + return -EINVAL; + +- auth = construct_auth(PKS_OS_OWNER); ++ auth = construct_auth(consumer); + if (IS_ERR(auth)) + return PTR_ERR(auth); + +- label = construct_label(var->component, var->os, var->name, +- var->namelen); +- if (IS_ERR(label)) { +- rc = PTR_ERR(label); +- goto out_free_auth; ++ if (consumer == PKS_OS_OWNER) { ++ label = construct_label(var->component, var->os, var->name, ++ var->namelen); ++ if (IS_ERR(label)) { ++ rc = PTR_ERR(label); ++ goto out_free_auth; ++ } + } + + output = kzalloc(maxobjsize, GFP_KERNEL); +@@ -390,9 +392,15 @@ static int plpks_read_var(u8 consumer, struct plpks_var *var) + goto out_free_label; + } + +- rc = plpar_hcall(H_PKS_READ_OBJECT, retbuf, virt_to_phys(auth), +- virt_to_phys(label), label->size, virt_to_phys(output), +- maxobjsize); ++ if (consumer == PKS_OS_OWNER) ++ rc = plpar_hcall(H_PKS_READ_OBJECT, retbuf, virt_to_phys(auth), ++ virt_to_phys(label), label->size, virt_to_phys(output), ++ maxobjsize); ++ else ++ rc = plpar_hcall(H_PKS_READ_OBJECT, retbuf, virt_to_phys(auth), ++ virt_to_phys(var->name), var->namelen, virt_to_phys(output), ++ maxobjsize); ++ + + if (rc != H_SUCCESS) { + pr_err("Failed to read variable %s for component %s with error %d\n", +diff --git a/arch/powerpc/platforms/pseries/plpks.h b/arch/powerpc/platforms/pseries/plpks.h +index c6a291367bb13..275ccd86bfb5e 100644 +--- a/arch/powerpc/platforms/pseries/plpks.h ++++ b/arch/powerpc/platforms/pseries/plpks.h +@@ -17,7 +17,7 @@ + #define WORLDREADABLE 0x08000000 + #define SIGNEDUPDATE 0x01000000 + +-#define PLPKS_VAR_LINUX 0x01 ++#define PLPKS_VAR_LINUX 0x02 + #define PLPKS_VAR_COMMON 0x04 + + struct plpks_var { +diff --git a/arch/powerpc/sysdev/xive/spapr.c b/arch/powerpc/sysdev/xive/spapr.c +index e2c8f93b535ba..e454192643910 100644 +--- a/arch/powerpc/sysdev/xive/spapr.c ++++ b/arch/powerpc/sysdev/xive/spapr.c +@@ -439,6 +439,7 @@ static int xive_spapr_populate_irq_data(u32 hw_irq, struct xive_irq_data *data) + + data->trig_mmio = ioremap(data->trig_page, 1u << data->esb_shift); + if (!data->trig_mmio) { ++ iounmap(data->eoi_mmio); + pr_err("Failed to map trigger page for irq 0x%x\n", hw_irq); + return -ENOMEM; + } +diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c +index f51c882bf9023..e34d7809f6c9f 100644 +--- a/arch/powerpc/xmon/xmon.c ++++ b/arch/powerpc/xmon/xmon.c +@@ -1525,9 +1525,9 @@ bpt_cmds(void) + cmd = inchar(); + + switch (cmd) { +- static const char badaddr[] = "Only kernel addresses are permitted for breakpoints\n"; +- int mode; +- case 'd': /* bd - hardware data breakpoint */ ++ case 'd': { /* bd - hardware data breakpoint */ ++ static const char badaddr[] = "Only kernel addresses are permitted for breakpoints\n"; ++ int mode; + if (xmon_is_ro) { + printf(xmon_ro_msg); + break; +@@ -1560,6 +1560,7 @@ bpt_cmds(void) + + force_enable_xmon(); + break; ++ } + + case 'i': /* bi - hardware instr breakpoint */ + if (xmon_is_ro) { +diff --git a/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-fabric.dtsi b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-fabric.dtsi +index 24b1cfb9a73e4..5d3e5240e33ae 100644 +--- a/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-fabric.dtsi ++++ b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-fabric.dtsi +@@ -9,7 +9,7 @@ + compatible = "microchip,corepwm-rtl-v4"; + reg = <0x0 0x40000000 0x0 0xF0>; + microchip,sync-update-mask = /bits/ 32 <0>; +- #pwm-cells = <2>; ++ #pwm-cells = <3>; + clocks = <&fabric_clk3>; + status = "disabled"; + }; +diff --git a/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts +index ec7b7c2a3ce28..8ced67c3b00b2 100644 +--- a/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts ++++ b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts +@@ -37,7 +37,7 @@ + status = "okay"; + }; + +- ddrc_cache_hi: memory@1000000000 { ++ ddrc_cache_hi: memory@1040000000 { + device_type = "memory"; + reg = <0x10 0x40000000 0x0 0x40000000>; + status = "okay"; +diff --git a/arch/riscv/boot/dts/microchip/mpfs-sev-kit-fabric.dtsi b/arch/riscv/boot/dts/microchip/mpfs-sev-kit-fabric.dtsi +index 8545baf4d1290..39a77df489abf 100644 +--- a/arch/riscv/boot/dts/microchip/mpfs-sev-kit-fabric.dtsi ++++ b/arch/riscv/boot/dts/microchip/mpfs-sev-kit-fabric.dtsi +@@ -13,33 +13,4 @@ + #clock-cells = <0>; + clock-frequency = <125000000>; + }; +- +- pcie: pcie@2000000000 { +- compatible = "microchip,pcie-host-1.0"; +- #address-cells = <0x3>; +- #interrupt-cells = <0x1>; +- #size-cells = <0x2>; +- device_type = "pci"; +- reg = <0x20 0x0 0x0 0x8000000>, <0x0 0x43000000 0x0 0x10000>; +- reg-names = "cfg", "apb"; +- bus-range = <0x0 0x7f>; +- interrupt-parent = <&plic>; +- interrupts = <119>; +- interrupt-map = <0 0 0 1 &pcie_intc 0>, +- <0 0 0 2 &pcie_intc 1>, +- <0 0 0 3 &pcie_intc 2>, +- <0 0 0 4 &pcie_intc 3>; +- interrupt-map-mask = <0 0 0 7>; +- clocks = <&fabric_clk1>, <&fabric_clk1>, <&fabric_clk3>; +- clock-names = "fic0", "fic1", "fic3"; +- ranges = <0x3000000 0x0 0x8000000 0x20 0x8000000 0x0 0x80000000>; +- msi-parent = <&pcie>; +- msi-controller; +- status = "disabled"; +- pcie_intc: interrupt-controller { +- #address-cells = <0>; +- #interrupt-cells = <1>; +- interrupt-controller; +- }; +- }; + }; +diff --git a/arch/riscv/include/asm/hugetlb.h b/arch/riscv/include/asm/hugetlb.h +index a5c2ca1d1cd8b..ec19d6afc8965 100644 +--- a/arch/riscv/include/asm/hugetlb.h ++++ b/arch/riscv/include/asm/hugetlb.h +@@ -5,4 +5,10 @@ + #include <asm-generic/hugetlb.h> + #include <asm/page.h> + ++static inline void arch_clear_hugepage_flags(struct page *page) ++{ ++ clear_bit(PG_dcache_clean, &page->flags); ++} ++#define arch_clear_hugepage_flags arch_clear_hugepage_flags ++ + #endif /* _ASM_RISCV_HUGETLB_H */ +diff --git a/arch/riscv/include/asm/io.h b/arch/riscv/include/asm/io.h +index 92080a2279372..42497d487a174 100644 +--- a/arch/riscv/include/asm/io.h ++++ b/arch/riscv/include/asm/io.h +@@ -135,4 +135,9 @@ __io_writes_outs(outs, u64, q, __io_pbr(), __io_paw()) + + #include <asm-generic/io.h> + ++#ifdef CONFIG_MMU ++#define arch_memremap_wb(addr, size) \ ++ ((__force void *)ioremap_prot((addr), (size), _PAGE_KERNEL)) ++#endif ++ + #endif /* _ASM_RISCV_IO_H */ +diff --git a/arch/riscv/include/asm/pgtable-64.h b/arch/riscv/include/asm/pgtable-64.h +index dc42375c23571..42a042c0e13ed 100644 +--- a/arch/riscv/include/asm/pgtable-64.h ++++ b/arch/riscv/include/asm/pgtable-64.h +@@ -25,7 +25,11 @@ extern bool pgtable_l5_enabled; + #define PGDIR_MASK (~(PGDIR_SIZE - 1)) + + /* p4d is folded into pgd in case of 4-level page table */ +-#define P4D_SHIFT 39 ++#define P4D_SHIFT_L3 30 ++#define P4D_SHIFT_L4 39 ++#define P4D_SHIFT_L5 39 ++#define P4D_SHIFT (pgtable_l5_enabled ? P4D_SHIFT_L5 : \ ++ (pgtable_l4_enabled ? P4D_SHIFT_L4 : P4D_SHIFT_L3)) + #define P4D_SIZE (_AC(1, UL) << P4D_SHIFT) + #define P4D_MASK (~(P4D_SIZE - 1)) + +diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S +index 186abd146eaff..3221a9e5f3724 100644 +--- a/arch/riscv/kernel/entry.S ++++ b/arch/riscv/kernel/entry.S +@@ -263,12 +263,11 @@ ret_from_exception: + #endif + bnez s0, resume_kernel + +-resume_userspace: + /* Interrupts must be disabled here so flags are checked atomically */ + REG_L s0, TASK_TI_FLAGS(tp) /* current_thread_info->flags */ + andi s1, s0, _TIF_WORK_MASK +- bnez s1, work_pending +- ++ bnez s1, resume_userspace_slow ++resume_userspace: + #ifdef CONFIG_CONTEXT_TRACKING_USER + call user_enter_callable + #endif +@@ -368,19 +367,12 @@ resume_kernel: + j restore_all + #endif + +-work_pending: ++resume_userspace_slow: + /* Enter slow path for supplementary processing */ +- la ra, ret_from_exception +- andi s1, s0, _TIF_NEED_RESCHED +- bnez s1, work_resched +-work_notifysig: +- /* Handle pending signals and notify-resume requests */ +- csrs CSR_STATUS, SR_IE /* Enable interrupts for do_notify_resume() */ + move a0, sp /* pt_regs */ + move a1, s0 /* current_thread_info->flags */ +- tail do_notify_resume +-work_resched: +- tail schedule ++ call do_work_pending ++ j resume_userspace + + /* Slow paths for ptrace. */ + handle_syscall_trace_enter: +diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c +index 5c591123c4409..bfb2afa4135f8 100644 +--- a/arch/riscv/kernel/signal.c ++++ b/arch/riscv/kernel/signal.c +@@ -313,19 +313,27 @@ static void do_signal(struct pt_regs *regs) + } + + /* +- * notification of userspace execution resumption +- * - triggered by the _TIF_WORK_MASK flags ++ * Handle any pending work on the resume-to-userspace path, as indicated by ++ * _TIF_WORK_MASK. Entered from assembly with IRQs off. + */ +-asmlinkage __visible void do_notify_resume(struct pt_regs *regs, +- unsigned long thread_info_flags) ++asmlinkage __visible void do_work_pending(struct pt_regs *regs, ++ unsigned long thread_info_flags) + { +- if (thread_info_flags & _TIF_UPROBE) +- uprobe_notify_resume(regs); +- +- /* Handle pending signal delivery */ +- if (thread_info_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) +- do_signal(regs); +- +- if (thread_info_flags & _TIF_NOTIFY_RESUME) +- resume_user_mode_work(regs); ++ do { ++ if (thread_info_flags & _TIF_NEED_RESCHED) { ++ schedule(); ++ } else { ++ local_irq_enable(); ++ if (thread_info_flags & _TIF_UPROBE) ++ uprobe_notify_resume(regs); ++ /* Handle pending signal delivery */ ++ if (thread_info_flags & (_TIF_SIGPENDING | ++ _TIF_NOTIFY_SIGNAL)) ++ do_signal(regs); ++ if (thread_info_flags & _TIF_NOTIFY_RESUME) ++ resume_user_mode_work(regs); ++ } ++ local_irq_disable(); ++ thread_info_flags = read_thread_flags(); ++ } while (thread_info_flags & _TIF_WORK_MASK); + } +diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c +index 7abd8e4c4df63..f77cb8e42bd2a 100644 +--- a/arch/riscv/kernel/traps.c ++++ b/arch/riscv/kernel/traps.c +@@ -214,7 +214,7 @@ static DEFINE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], + * shadow stack, handled_ kernel_ stack_ overflow(in kernel/entry.S) is used + * to get per-cpu overflow stack(get_overflow_stack). + */ +-long shadow_stack[SHADOW_OVERFLOW_STACK_SIZE/sizeof(long)]; ++long shadow_stack[SHADOW_OVERFLOW_STACK_SIZE/sizeof(long)] __aligned(16); + asmlinkage unsigned long get_overflow_stack(void) + { + return (unsigned long)this_cpu_ptr(overflow_stack) + +diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c +index 71ebbc4821f0e..5174ef54ad1d9 100644 +--- a/arch/riscv/kvm/vcpu.c ++++ b/arch/riscv/kvm/vcpu.c +@@ -296,12 +296,15 @@ static int kvm_riscv_vcpu_set_reg_config(struct kvm_vcpu *vcpu, + if (copy_from_user(®_val, uaddr, KVM_REG_SIZE(reg->id))) + return -EFAULT; + +- /* This ONE REG interface is only defined for single letter extensions */ +- if (fls(reg_val) >= RISCV_ISA_EXT_BASE) +- return -EINVAL; +- + switch (reg_num) { + case KVM_REG_RISCV_CONFIG_REG(isa): ++ /* ++ * This ONE REG interface is only defined for ++ * single letter extensions. ++ */ ++ if (fls(reg_val) >= RISCV_ISA_EXT_BASE) ++ return -EINVAL; ++ + if (!vcpu->arch.ran_atleast_once) { + /* Ignore the enable/disable request for certain extensions */ + for (i = 0; i < RISCV_ISA_EXT_BASE; i++) { +diff --git a/arch/riscv/mm/physaddr.c b/arch/riscv/mm/physaddr.c +index 19cf25a74ee29..9b18bda74154e 100644 +--- a/arch/riscv/mm/physaddr.c ++++ b/arch/riscv/mm/physaddr.c +@@ -22,7 +22,7 @@ EXPORT_SYMBOL(__virt_to_phys); + phys_addr_t __phys_addr_symbol(unsigned long x) + { + unsigned long kernel_start = kernel_map.virt_addr; +- unsigned long kernel_end = (unsigned long)_end; ++ unsigned long kernel_end = kernel_start + kernel_map.size; + + /* + * Boundary checking aginst the kernel image mapping. +diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c +index 00df3a8f92acd..f2417ac54edd6 100644 +--- a/arch/riscv/net/bpf_jit_comp64.c ++++ b/arch/riscv/net/bpf_jit_comp64.c +@@ -136,6 +136,25 @@ static bool in_auipc_jalr_range(s64 val) + val < ((1L << 31) - (1L << 11)); + } + ++/* Emit fixed-length instructions for address */ ++static int emit_addr(u8 rd, u64 addr, bool extra_pass, struct rv_jit_context *ctx) ++{ ++ u64 ip = (u64)(ctx->insns + ctx->ninsns); ++ s64 off = addr - ip; ++ s64 upper = (off + (1 << 11)) >> 12; ++ s64 lower = off & 0xfff; ++ ++ if (extra_pass && !in_auipc_jalr_range(off)) { ++ pr_err("bpf-jit: target offset 0x%llx is out of range\n", off); ++ return -ERANGE; ++ } ++ ++ emit(rv_auipc(rd, upper), ctx); ++ emit(rv_addi(rd, rd, lower), ctx); ++ return 0; ++} ++ ++/* Emit variable-length instructions for 32-bit and 64-bit imm */ + static void emit_imm(u8 rd, s64 val, struct rv_jit_context *ctx) + { + /* Note that the immediate from the add is sign-extended, +@@ -1050,7 +1069,15 @@ out_be: + u64 imm64; + + imm64 = (u64)insn1.imm << 32 | (u32)imm; +- emit_imm(rd, imm64, ctx); ++ if (bpf_pseudo_func(insn)) { ++ /* fixed-length insns for extra jit pass */ ++ ret = emit_addr(rd, imm64, extra_pass, ctx); ++ if (ret) ++ return ret; ++ } else { ++ emit_imm(rd, imm64, ctx); ++ } ++ + return 1; + } + +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index 67745ceab0dbc..b2c0fce3f257c 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -462,8 +462,8 @@ config X86_X2APIC + + Some Intel systems circa 2022 and later are locked into x2APIC mode + and can not fall back to the legacy APIC modes if SGX or TDX are +- enabled in the BIOS. They will be unable to boot without enabling +- this option. ++ enabled in the BIOS. They will boot with very reduced functionality ++ without enabling this option. + + If you don't know what to do here, say N. + +diff --git a/arch/x86/crypto/aegis128-aesni-asm.S b/arch/x86/crypto/aegis128-aesni-asm.S +index b48ddebb47489..cdf3215ec272c 100644 +--- a/arch/x86/crypto/aegis128-aesni-asm.S ++++ b/arch/x86/crypto/aegis128-aesni-asm.S +@@ -7,6 +7,7 @@ + */ + + #include <linux/linkage.h> ++#include <linux/cfi_types.h> + #include <asm/frame.h> + + #define STATE0 %xmm0 +@@ -402,7 +403,7 @@ SYM_FUNC_END(crypto_aegis128_aesni_ad) + * void crypto_aegis128_aesni_enc(void *state, unsigned int length, + * const void *src, void *dst); + */ +-SYM_FUNC_START(crypto_aegis128_aesni_enc) ++SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc) + FRAME_BEGIN + + cmp $0x10, LEN +@@ -499,7 +500,7 @@ SYM_FUNC_END(crypto_aegis128_aesni_enc) + * void crypto_aegis128_aesni_enc_tail(void *state, unsigned int length, + * const void *src, void *dst); + */ +-SYM_FUNC_START(crypto_aegis128_aesni_enc_tail) ++SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc_tail) + FRAME_BEGIN + + /* load the state: */ +@@ -556,7 +557,7 @@ SYM_FUNC_END(crypto_aegis128_aesni_enc_tail) + * void crypto_aegis128_aesni_dec(void *state, unsigned int length, + * const void *src, void *dst); + */ +-SYM_FUNC_START(crypto_aegis128_aesni_dec) ++SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec) + FRAME_BEGIN + + cmp $0x10, LEN +@@ -653,7 +654,7 @@ SYM_FUNC_END(crypto_aegis128_aesni_dec) + * void crypto_aegis128_aesni_dec_tail(void *state, unsigned int length, + * const void *src, void *dst); + */ +-SYM_FUNC_START(crypto_aegis128_aesni_dec_tail) ++SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec_tail) + FRAME_BEGIN + + /* load the state: */ +diff --git a/arch/x86/crypto/aria-aesni-avx-asm_64.S b/arch/x86/crypto/aria-aesni-avx-asm_64.S +index c75fd7d015ed8..03ae4cd1d976a 100644 +--- a/arch/x86/crypto/aria-aesni-avx-asm_64.S ++++ b/arch/x86/crypto/aria-aesni-avx-asm_64.S +@@ -7,6 +7,7 @@ + */ + + #include <linux/linkage.h> ++#include <linux/cfi_types.h> + #include <asm/frame.h> + + /* struct aria_ctx: */ +@@ -913,7 +914,7 @@ SYM_FUNC_START_LOCAL(__aria_aesni_avx_crypt_16way) + RET; + SYM_FUNC_END(__aria_aesni_avx_crypt_16way) + +-SYM_FUNC_START(aria_aesni_avx_encrypt_16way) ++SYM_TYPED_FUNC_START(aria_aesni_avx_encrypt_16way) + /* input: + * %rdi: ctx, CTX + * %rsi: dst +@@ -938,7 +939,7 @@ SYM_FUNC_START(aria_aesni_avx_encrypt_16way) + RET; + SYM_FUNC_END(aria_aesni_avx_encrypt_16way) + +-SYM_FUNC_START(aria_aesni_avx_decrypt_16way) ++SYM_TYPED_FUNC_START(aria_aesni_avx_decrypt_16way) + /* input: + * %rdi: ctx, CTX + * %rsi: dst +@@ -1039,7 +1040,7 @@ SYM_FUNC_START_LOCAL(__aria_aesni_avx_ctr_gen_keystream_16way) + RET; + SYM_FUNC_END(__aria_aesni_avx_ctr_gen_keystream_16way) + +-SYM_FUNC_START(aria_aesni_avx_ctr_crypt_16way) ++SYM_TYPED_FUNC_START(aria_aesni_avx_ctr_crypt_16way) + /* input: + * %rdi: ctx + * %rsi: dst +@@ -1208,7 +1209,7 @@ SYM_FUNC_START_LOCAL(__aria_aesni_avx_gfni_crypt_16way) + RET; + SYM_FUNC_END(__aria_aesni_avx_gfni_crypt_16way) + +-SYM_FUNC_START(aria_aesni_avx_gfni_encrypt_16way) ++SYM_TYPED_FUNC_START(aria_aesni_avx_gfni_encrypt_16way) + /* input: + * %rdi: ctx, CTX + * %rsi: dst +@@ -1233,7 +1234,7 @@ SYM_FUNC_START(aria_aesni_avx_gfni_encrypt_16way) + RET; + SYM_FUNC_END(aria_aesni_avx_gfni_encrypt_16way) + +-SYM_FUNC_START(aria_aesni_avx_gfni_decrypt_16way) ++SYM_TYPED_FUNC_START(aria_aesni_avx_gfni_decrypt_16way) + /* input: + * %rdi: ctx, CTX + * %rsi: dst +@@ -1258,7 +1259,7 @@ SYM_FUNC_START(aria_aesni_avx_gfni_decrypt_16way) + RET; + SYM_FUNC_END(aria_aesni_avx_gfni_decrypt_16way) + +-SYM_FUNC_START(aria_aesni_avx_gfni_ctr_crypt_16way) ++SYM_TYPED_FUNC_START(aria_aesni_avx_gfni_ctr_crypt_16way) + /* input: + * %rdi: ctx + * %rsi: dst +diff --git a/arch/x86/crypto/sha1_ni_asm.S b/arch/x86/crypto/sha1_ni_asm.S +index 2f94ec0e763bf..3cae5a1bb3d6e 100644 +--- a/arch/x86/crypto/sha1_ni_asm.S ++++ b/arch/x86/crypto/sha1_ni_asm.S +@@ -54,6 +54,7 @@ + */ + + #include <linux/linkage.h> ++#include <linux/cfi_types.h> + + #define DIGEST_PTR %rdi /* 1st arg */ + #define DATA_PTR %rsi /* 2nd arg */ +@@ -93,7 +94,7 @@ + */ + .text + .align 32 +-SYM_FUNC_START(sha1_ni_transform) ++SYM_TYPED_FUNC_START(sha1_ni_transform) + push %rbp + mov %rsp, %rbp + sub $FRAME_SIZE, %rsp +diff --git a/arch/x86/crypto/sha1_ssse3_asm.S b/arch/x86/crypto/sha1_ssse3_asm.S +index 263f916362e02..f54988c80eb40 100644 +--- a/arch/x86/crypto/sha1_ssse3_asm.S ++++ b/arch/x86/crypto/sha1_ssse3_asm.S +@@ -25,6 +25,7 @@ + */ + + #include <linux/linkage.h> ++#include <linux/cfi_types.h> + + #define CTX %rdi // arg1 + #define BUF %rsi // arg2 +@@ -67,7 +68,7 @@ + * param: function's name + */ + .macro SHA1_VECTOR_ASM name +- SYM_FUNC_START(\name) ++ SYM_TYPED_FUNC_START(\name) + + push %rbx + push %r12 +diff --git a/arch/x86/crypto/sha256-avx-asm.S b/arch/x86/crypto/sha256-avx-asm.S +index 3baa1ec390974..06ea30c20828d 100644 +--- a/arch/x86/crypto/sha256-avx-asm.S ++++ b/arch/x86/crypto/sha256-avx-asm.S +@@ -48,6 +48,7 @@ + ######################################################################## + + #include <linux/linkage.h> ++#include <linux/cfi_types.h> + + ## assume buffers not aligned + #define VMOVDQ vmovdqu +@@ -346,7 +347,7 @@ a = TMP_ + ## arg 3 : Num blocks + ######################################################################## + .text +-SYM_FUNC_START(sha256_transform_avx) ++SYM_TYPED_FUNC_START(sha256_transform_avx) + .align 32 + pushq %rbx + pushq %r12 +diff --git a/arch/x86/crypto/sha256-avx2-asm.S b/arch/x86/crypto/sha256-avx2-asm.S +index 9bcdbc47b8b4b..2d2be531a11ed 100644 +--- a/arch/x86/crypto/sha256-avx2-asm.S ++++ b/arch/x86/crypto/sha256-avx2-asm.S +@@ -49,6 +49,7 @@ + ######################################################################## + + #include <linux/linkage.h> ++#include <linux/cfi_types.h> + + ## assume buffers not aligned + #define VMOVDQ vmovdqu +@@ -523,7 +524,7 @@ STACK_SIZE = _CTX + _CTX_SIZE + ## arg 3 : Num blocks + ######################################################################## + .text +-SYM_FUNC_START(sha256_transform_rorx) ++SYM_TYPED_FUNC_START(sha256_transform_rorx) + .align 32 + pushq %rbx + pushq %r12 +diff --git a/arch/x86/crypto/sha256-ssse3-asm.S b/arch/x86/crypto/sha256-ssse3-asm.S +index c4a5db612c327..7db28839108dd 100644 +--- a/arch/x86/crypto/sha256-ssse3-asm.S ++++ b/arch/x86/crypto/sha256-ssse3-asm.S +@@ -47,6 +47,7 @@ + ######################################################################## + + #include <linux/linkage.h> ++#include <linux/cfi_types.h> + + ## assume buffers not aligned + #define MOVDQ movdqu +@@ -355,7 +356,7 @@ a = TMP_ + ## arg 3 : Num blocks + ######################################################################## + .text +-SYM_FUNC_START(sha256_transform_ssse3) ++SYM_TYPED_FUNC_START(sha256_transform_ssse3) + .align 32 + pushq %rbx + pushq %r12 +diff --git a/arch/x86/crypto/sha256_ni_asm.S b/arch/x86/crypto/sha256_ni_asm.S +index 94d50dd27cb53..47f93937f798a 100644 +--- a/arch/x86/crypto/sha256_ni_asm.S ++++ b/arch/x86/crypto/sha256_ni_asm.S +@@ -54,6 +54,7 @@ + */ + + #include <linux/linkage.h> ++#include <linux/cfi_types.h> + + #define DIGEST_PTR %rdi /* 1st arg */ + #define DATA_PTR %rsi /* 2nd arg */ +@@ -97,7 +98,7 @@ + + .text + .align 32 +-SYM_FUNC_START(sha256_ni_transform) ++SYM_TYPED_FUNC_START(sha256_ni_transform) + + shl $6, NUM_BLKS /* convert to bytes */ + jz .Ldone_hash +diff --git a/arch/x86/crypto/sha512-avx-asm.S b/arch/x86/crypto/sha512-avx-asm.S +index 1fefe6dd3a9e2..b0984f19fdb40 100644 +--- a/arch/x86/crypto/sha512-avx-asm.S ++++ b/arch/x86/crypto/sha512-avx-asm.S +@@ -48,6 +48,7 @@ + ######################################################################## + + #include <linux/linkage.h> ++#include <linux/cfi_types.h> + + .text + +@@ -273,7 +274,7 @@ frame_size = frame_WK + WK_SIZE + # of SHA512 message blocks. + # "blocks" is the message length in SHA512 blocks + ######################################################################## +-SYM_FUNC_START(sha512_transform_avx) ++SYM_TYPED_FUNC_START(sha512_transform_avx) + test msglen, msglen + je nowork + +diff --git a/arch/x86/crypto/sha512-avx2-asm.S b/arch/x86/crypto/sha512-avx2-asm.S +index 5cdaab7d69015..b1ca99055ef99 100644 +--- a/arch/x86/crypto/sha512-avx2-asm.S ++++ b/arch/x86/crypto/sha512-avx2-asm.S +@@ -50,6 +50,7 @@ + ######################################################################## + + #include <linux/linkage.h> ++#include <linux/cfi_types.h> + + .text + +@@ -565,7 +566,7 @@ frame_size = frame_CTX + CTX_SIZE + # of SHA512 message blocks. + # "blocks" is the message length in SHA512 blocks + ######################################################################## +-SYM_FUNC_START(sha512_transform_rorx) ++SYM_TYPED_FUNC_START(sha512_transform_rorx) + # Save GPRs + push %rbx + push %r12 +diff --git a/arch/x86/crypto/sha512-ssse3-asm.S b/arch/x86/crypto/sha512-ssse3-asm.S +index b84c22e06c5f7..c06afb5270e5f 100644 +--- a/arch/x86/crypto/sha512-ssse3-asm.S ++++ b/arch/x86/crypto/sha512-ssse3-asm.S +@@ -48,6 +48,7 @@ + ######################################################################## + + #include <linux/linkage.h> ++#include <linux/cfi_types.h> + + .text + +@@ -274,7 +275,7 @@ frame_size = frame_WK + WK_SIZE + # of SHA512 message blocks. + # "blocks" is the message length in SHA512 blocks. + ######################################################################## +-SYM_FUNC_START(sha512_transform_ssse3) ++SYM_TYPED_FUNC_START(sha512_transform_ssse3) + + test msglen, msglen + je nowork +diff --git a/arch/x86/crypto/sm3-avx-asm_64.S b/arch/x86/crypto/sm3-avx-asm_64.S +index b12b9efb5ec51..8fc5ac681fd63 100644 +--- a/arch/x86/crypto/sm3-avx-asm_64.S ++++ b/arch/x86/crypto/sm3-avx-asm_64.S +@@ -12,6 +12,7 @@ + */ + + #include <linux/linkage.h> ++#include <linux/cfi_types.h> + #include <asm/frame.h> + + /* Context structure */ +@@ -328,7 +329,7 @@ + * const u8 *data, int nblocks); + */ + .align 16 +-SYM_FUNC_START(sm3_transform_avx) ++SYM_TYPED_FUNC_START(sm3_transform_avx) + /* input: + * %rdi: ctx, CTX + * %rsi: data (64*nblks bytes) +diff --git a/arch/x86/crypto/sm4-aesni-avx-asm_64.S b/arch/x86/crypto/sm4-aesni-avx-asm_64.S +index 4767ab61ff489..22b6560eb9e1e 100644 +--- a/arch/x86/crypto/sm4-aesni-avx-asm_64.S ++++ b/arch/x86/crypto/sm4-aesni-avx-asm_64.S +@@ -14,6 +14,7 @@ + */ + + #include <linux/linkage.h> ++#include <linux/cfi_types.h> + #include <asm/frame.h> + + #define rRIP (%rip) +@@ -420,7 +421,7 @@ SYM_FUNC_END(sm4_aesni_avx_crypt8) + * const u8 *src, u8 *iv) + */ + .align 8 +-SYM_FUNC_START(sm4_aesni_avx_ctr_enc_blk8) ++SYM_TYPED_FUNC_START(sm4_aesni_avx_ctr_enc_blk8) + /* input: + * %rdi: round key array, CTX + * %rsi: dst (8 blocks) +@@ -495,7 +496,7 @@ SYM_FUNC_END(sm4_aesni_avx_ctr_enc_blk8) + * const u8 *src, u8 *iv) + */ + .align 8 +-SYM_FUNC_START(sm4_aesni_avx_cbc_dec_blk8) ++SYM_TYPED_FUNC_START(sm4_aesni_avx_cbc_dec_blk8) + /* input: + * %rdi: round key array, CTX + * %rsi: dst (8 blocks) +@@ -545,7 +546,7 @@ SYM_FUNC_END(sm4_aesni_avx_cbc_dec_blk8) + * const u8 *src, u8 *iv) + */ + .align 8 +-SYM_FUNC_START(sm4_aesni_avx_cfb_dec_blk8) ++SYM_TYPED_FUNC_START(sm4_aesni_avx_cfb_dec_blk8) + /* input: + * %rdi: round key array, CTX + * %rsi: dst (8 blocks) +diff --git a/arch/x86/crypto/sm4-aesni-avx2-asm_64.S b/arch/x86/crypto/sm4-aesni-avx2-asm_64.S +index 4732fe8bb65b6..23ee39a8ada8c 100644 +--- a/arch/x86/crypto/sm4-aesni-avx2-asm_64.S ++++ b/arch/x86/crypto/sm4-aesni-avx2-asm_64.S +@@ -14,6 +14,7 @@ + */ + + #include <linux/linkage.h> ++#include <linux/cfi_types.h> + #include <asm/frame.h> + + #define rRIP (%rip) +@@ -282,7 +283,7 @@ SYM_FUNC_END(__sm4_crypt_blk16) + * const u8 *src, u8 *iv) + */ + .align 8 +-SYM_FUNC_START(sm4_aesni_avx2_ctr_enc_blk16) ++SYM_TYPED_FUNC_START(sm4_aesni_avx2_ctr_enc_blk16) + /* input: + * %rdi: round key array, CTX + * %rsi: dst (16 blocks) +@@ -395,7 +396,7 @@ SYM_FUNC_END(sm4_aesni_avx2_ctr_enc_blk16) + * const u8 *src, u8 *iv) + */ + .align 8 +-SYM_FUNC_START(sm4_aesni_avx2_cbc_dec_blk16) ++SYM_TYPED_FUNC_START(sm4_aesni_avx2_cbc_dec_blk16) + /* input: + * %rdi: round key array, CTX + * %rsi: dst (16 blocks) +@@ -449,7 +450,7 @@ SYM_FUNC_END(sm4_aesni_avx2_cbc_dec_blk16) + * const u8 *src, u8 *iv) + */ + .align 8 +-SYM_FUNC_START(sm4_aesni_avx2_cfb_dec_blk16) ++SYM_TYPED_FUNC_START(sm4_aesni_avx2_cfb_dec_blk16) + /* input: + * %rdi: round key array, CTX + * %rsi: dst (16 blocks) +diff --git a/arch/x86/entry/vdso/vdso.lds.S b/arch/x86/entry/vdso/vdso.lds.S +index 4bf48462fca7a..e8c60ae7a7c83 100644 +--- a/arch/x86/entry/vdso/vdso.lds.S ++++ b/arch/x86/entry/vdso/vdso.lds.S +@@ -27,7 +27,9 @@ VERSION { + __vdso_time; + clock_getres; + __vdso_clock_getres; ++#ifdef CONFIG_X86_SGX + __vdso_sgx_enter_enclave; ++#endif + local: *; + }; + } +diff --git a/arch/x86/events/intel/uncore_snb.c b/arch/x86/events/intel/uncore_snb.c +index 1ef4f7861e2ec..1f4869227efb9 100644 +--- a/arch/x86/events/intel/uncore_snb.c ++++ b/arch/x86/events/intel/uncore_snb.c +@@ -1338,6 +1338,7 @@ static void __uncore_imc_init_box(struct intel_uncore_box *box, + /* MCHBAR is disabled */ + if (!(mch_bar & BIT(0))) { + pr_warn("perf uncore: MCHBAR is disabled. Failed to map IMC free-running counters.\n"); ++ pci_dev_put(pdev); + return; + } + mch_bar &= ~BIT(0); +@@ -1352,6 +1353,8 @@ static void __uncore_imc_init_box(struct intel_uncore_box *box, + box->io_addr = ioremap(addr, type->mmio_map_size); + if (!box->io_addr) + pr_warn("perf uncore: Failed to ioremap for %s.\n", type->name); ++ ++ pci_dev_put(pdev); + } + + static void tgl_uncore_imc_freerunning_init_box(struct intel_uncore_box *box) +diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c +index ed869443efb21..fcd95e93f479a 100644 +--- a/arch/x86/events/intel/uncore_snbep.c ++++ b/arch/x86/events/intel/uncore_snbep.c +@@ -2891,6 +2891,7 @@ static bool hswep_has_limit_sbox(unsigned int device) + return false; + + pci_read_config_dword(dev, HSWEP_PCU_CAPID4_OFFET, &capid4); ++ pci_dev_put(dev); + if (!hswep_get_chop(capid4)) + return true; + +@@ -4492,6 +4493,8 @@ static int sad_cfg_iio_topology(struct intel_uncore_type *type, u8 *sad_pmon_map + type->topology = NULL; + } + ++ pci_dev_put(dev); ++ + return ret; + } + +@@ -4857,6 +4860,8 @@ static int snr_uncore_mmio_map(struct intel_uncore_box *box, + + addr += box_ctl; + ++ pci_dev_put(pdev); ++ + box->io_addr = ioremap(addr, type->mmio_map_size); + if (!box->io_addr) { + pr_warn("perf uncore: Failed to ioremap for %s.\n", type->name); +diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c +index a269049a43ce3..85863b9c9e684 100644 +--- a/arch/x86/hyperv/hv_init.c ++++ b/arch/x86/hyperv/hv_init.c +@@ -535,8 +535,6 @@ void hyperv_cleanup(void) + union hv_x64_msr_hypercall_contents hypercall_msr; + union hv_reference_tsc_msr tsc_msr; + +- unregister_syscore_ops(&hv_syscore_ops); +- + /* Reset our OS id */ + wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0); + hv_ghcb_msr_write(HV_X64_MSR_GUEST_OS_ID, 0); +diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h +index 3415321c8240c..3216da7074bad 100644 +--- a/arch/x86/include/asm/apic.h ++++ b/arch/x86/include/asm/apic.h +@@ -249,7 +249,6 @@ static inline u64 native_x2apic_icr_read(void) + extern int x2apic_mode; + extern int x2apic_phys; + extern void __init x2apic_set_max_apicid(u32 apicid); +-extern void __init check_x2apic(void); + extern void x2apic_setup(void); + static inline int x2apic_enabled(void) + { +@@ -258,13 +257,13 @@ static inline int x2apic_enabled(void) + + #define x2apic_supported() (boot_cpu_has(X86_FEATURE_X2APIC)) + #else /* !CONFIG_X86_X2APIC */ +-static inline void check_x2apic(void) { } + static inline void x2apic_setup(void) { } + static inline int x2apic_enabled(void) { return 0; } + + #define x2apic_mode (0) + #define x2apic_supported() (0) + #endif /* !CONFIG_X86_X2APIC */ ++extern void __init check_x2apic(void); + + struct irq_data; + +diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h +index fd6f6e5b755a7..a336feef0af14 100644 +--- a/arch/x86/include/asm/realmode.h ++++ b/arch/x86/include/asm/realmode.h +@@ -91,6 +91,7 @@ static inline void set_real_mode_mem(phys_addr_t mem) + + void reserve_real_mode(void); + void load_trampoline_pgtable(void); ++void init_real_mode(void); + + #endif /* __ASSEMBLY__ */ + +diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h +index e9170457697e4..c1c8c581759d6 100644 +--- a/arch/x86/include/asm/x86_init.h ++++ b/arch/x86/include/asm/x86_init.h +@@ -285,6 +285,8 @@ struct x86_hyper_runtime { + * possible in x86_early_init_platform_quirks() by + * only using the current x86_hardware_subarch + * semantics. ++ * @realmode_reserve: reserve memory for realmode trampoline ++ * @realmode_init: initialize realmode trampoline + * @hyper: x86 hypervisor specific runtime callbacks + */ + struct x86_platform_ops { +@@ -301,6 +303,8 @@ struct x86_platform_ops { + void (*apic_post_init)(void); + struct x86_legacy_features legacy; + void (*set_legacy_features)(void); ++ void (*realmode_reserve)(void); ++ void (*realmode_init)(void); + struct x86_hyper_runtime hyper; + struct x86_guest guest; + }; +diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c +index c6876d3ea4b17..20d9a604da7c4 100644 +--- a/arch/x86/kernel/apic/apic.c ++++ b/arch/x86/kernel/apic/apic.c +@@ -1931,16 +1931,19 @@ void __init check_x2apic(void) + } + } + #else /* CONFIG_X86_X2APIC */ +-static int __init validate_x2apic(void) ++void __init check_x2apic(void) + { + if (!apic_is_x2apic_enabled()) +- return 0; ++ return; + /* +- * Checkme: Can we simply turn off x2apic here instead of panic? ++ * Checkme: Can we simply turn off x2APIC here instead of disabling the APIC? + */ +- panic("BIOS has enabled x2apic but kernel doesn't support x2apic, please disable x2apic in BIOS.\n"); ++ pr_err("Kernel does not support x2APIC, please recompile with CONFIG_X86_X2APIC.\n"); ++ pr_err("Disabling APIC, expect reduced performance and functionality.\n"); ++ ++ disable_apic = 1; ++ setup_clear_cpu_cap(X86_FEATURE_APIC); + } +-early_initcall(validate_x2apic); + + static inline void try_to_enable_x2apic(int remap_mode) { } + static inline void __x2apic_enable(void) { } +diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c +index 2d7ea5480ec33..4278996504833 100644 +--- a/arch/x86/kernel/cpu/intel.c ++++ b/arch/x86/kernel/cpu/intel.c +@@ -1034,8 +1034,32 @@ static const struct { + + static struct ratelimit_state bld_ratelimit; + ++static unsigned int sysctl_sld_mitigate = 1; + static DEFINE_SEMAPHORE(buslock_sem); + ++#ifdef CONFIG_PROC_SYSCTL ++static struct ctl_table sld_sysctls[] = { ++ { ++ .procname = "split_lock_mitigate", ++ .data = &sysctl_sld_mitigate, ++ .maxlen = sizeof(unsigned int), ++ .mode = 0644, ++ .proc_handler = proc_douintvec_minmax, ++ .extra1 = SYSCTL_ZERO, ++ .extra2 = SYSCTL_ONE, ++ }, ++ {} ++}; ++ ++static int __init sld_mitigate_sysctl_init(void) ++{ ++ register_sysctl_init("kernel", sld_sysctls); ++ return 0; ++} ++ ++late_initcall(sld_mitigate_sysctl_init); ++#endif ++ + static inline bool match_option(const char *arg, int arglen, const char *opt) + { + int len = strlen(opt), ratelimit; +@@ -1146,12 +1170,20 @@ static void split_lock_init(void) + split_lock_verify_msr(sld_state != sld_off); + } + +-static void __split_lock_reenable(struct work_struct *work) ++static void __split_lock_reenable_unlock(struct work_struct *work) + { + sld_update_msr(true); + up(&buslock_sem); + } + ++static DECLARE_DELAYED_WORK(sl_reenable_unlock, __split_lock_reenable_unlock); ++ ++static void __split_lock_reenable(struct work_struct *work) ++{ ++ sld_update_msr(true); ++} ++static DECLARE_DELAYED_WORK(sl_reenable, __split_lock_reenable); ++ + /* + * If a CPU goes offline with pending delayed work to re-enable split lock + * detection then the delayed work will be executed on some other CPU. That +@@ -1169,10 +1201,9 @@ static int splitlock_cpu_offline(unsigned int cpu) + return 0; + } + +-static DECLARE_DELAYED_WORK(split_lock_reenable, __split_lock_reenable); +- + static void split_lock_warn(unsigned long ip) + { ++ struct delayed_work *work; + int cpu; + + if (!current->reported_split_lock) +@@ -1180,14 +1211,26 @@ static void split_lock_warn(unsigned long ip) + current->comm, current->pid, ip); + current->reported_split_lock = 1; + +- /* misery factor #1, sleep 10ms before trying to execute split lock */ +- if (msleep_interruptible(10) > 0) +- return; +- /* Misery factor #2, only allow one buslocked disabled core at a time */ +- if (down_interruptible(&buslock_sem) == -EINTR) +- return; ++ if (sysctl_sld_mitigate) { ++ /* ++ * misery factor #1: ++ * sleep 10ms before trying to execute split lock. ++ */ ++ if (msleep_interruptible(10) > 0) ++ return; ++ /* ++ * Misery factor #2: ++ * only allow one buslocked disabled core at a time. ++ */ ++ if (down_interruptible(&buslock_sem) == -EINTR) ++ return; ++ work = &sl_reenable_unlock; ++ } else { ++ work = &sl_reenable; ++ } ++ + cpu = get_cpu(); +- schedule_delayed_work_on(cpu, &split_lock_reenable, 2); ++ schedule_delayed_work_on(cpu, work, 2); + + /* Disable split lock detection on this CPU to make progress */ + sld_update_msr(false); +diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c +index 1ec20807de1e8..2c258255a6296 100644 +--- a/arch/x86/kernel/cpu/sgx/encl.c ++++ b/arch/x86/kernel/cpu/sgx/encl.c +@@ -680,11 +680,15 @@ const struct vm_operations_struct sgx_vm_ops = { + void sgx_encl_release(struct kref *ref) + { + struct sgx_encl *encl = container_of(ref, struct sgx_encl, refcount); ++ unsigned long max_page_index = PFN_DOWN(encl->base + encl->size - 1); + struct sgx_va_page *va_page; + struct sgx_encl_page *entry; +- unsigned long index; ++ unsigned long count = 0; ++ ++ XA_STATE(xas, &encl->page_array, PFN_DOWN(encl->base)); + +- xa_for_each(&encl->page_array, index, entry) { ++ xas_lock(&xas); ++ xas_for_each(&xas, entry, max_page_index) { + if (entry->epc_page) { + /* + * The page and its radix tree entry cannot be freed +@@ -699,9 +703,20 @@ void sgx_encl_release(struct kref *ref) + } + + kfree(entry); +- /* Invoke scheduler to prevent soft lockups. */ +- cond_resched(); ++ /* ++ * Invoke scheduler on every XA_CHECK_SCHED iteration ++ * to prevent soft lockups. ++ */ ++ if (!(++count % XA_CHECK_SCHED)) { ++ xas_pause(&xas); ++ xas_unlock(&xas); ++ ++ cond_resched(); ++ ++ xas_lock(&xas); ++ } + } ++ xas_unlock(&xas); + + xa_destroy(&encl->page_array); + +diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c +index 216fee7144eef..892609cde4a20 100644 +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -1175,7 +1175,7 @@ void __init setup_arch(char **cmdline_p) + * Moreover, on machines with SandyBridge graphics or in setups that use + * crashkernel the entire 1M is reserved anyway. + */ +- reserve_real_mode(); ++ x86_platform.realmode_reserve(); + + init_mem_mapping(); + +diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c +index b63cf8f7745ee..6c07f6daaa227 100644 +--- a/arch/x86/kernel/uprobes.c ++++ b/arch/x86/kernel/uprobes.c +@@ -722,8 +722,9 @@ static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn) + switch (opc1) { + case 0xeb: /* jmp 8 */ + case 0xe9: /* jmp 32 */ +- case 0x90: /* prefix* + nop; same as jmp with .offs = 0 */ + break; ++ case 0x90: /* prefix* + nop; same as jmp with .offs = 0 */ ++ goto setup; + + case 0xe8: /* call relative */ + branch_clear_offset(auprobe, insn); +@@ -753,6 +754,7 @@ static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn) + return -ENOTSUPP; + } + ++setup: + auprobe->branch.opc1 = opc1; + auprobe->branch.ilen = insn->length; + auprobe->branch.offs = insn->immediate.value; +diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c +index 57353519bc119..ef80d361b4632 100644 +--- a/arch/x86/kernel/x86_init.c ++++ b/arch/x86/kernel/x86_init.c +@@ -25,6 +25,7 @@ + #include <asm/iommu.h> + #include <asm/mach_traps.h> + #include <asm/irqdomain.h> ++#include <asm/realmode.h> + + void x86_init_noop(void) { } + void __init x86_init_uint_noop(unsigned int unused) { } +@@ -145,6 +146,8 @@ struct x86_platform_ops x86_platform __ro_after_init = { + .get_nmi_reason = default_get_nmi_reason, + .save_sched_clock_state = tsc_save_sched_clock_state, + .restore_sched_clock_state = tsc_restore_sched_clock_state, ++ .realmode_reserve = reserve_real_mode, ++ .realmode_init = init_real_mode, + .hyper.pin_vcpu = x86_op_int_noop, + + .guest = { +diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c +index 41d7669a97ad1..af565816d2ba6 100644 +--- a/arch/x86/realmode/init.c ++++ b/arch/x86/realmode/init.c +@@ -200,14 +200,18 @@ static void __init set_real_mode_permissions(void) + set_memory_x((unsigned long) text_start, text_size >> PAGE_SHIFT); + } + +-static int __init init_real_mode(void) ++void __init init_real_mode(void) + { + if (!real_mode_header) + panic("Real mode trampoline was not allocated"); + + setup_real_mode(); + set_real_mode_permissions(); ++} + ++static int __init do_init_real_mode(void) ++{ ++ x86_platform.realmode_init(); + return 0; + } +-early_initcall(init_real_mode); ++early_initcall(do_init_real_mode); +diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c +index 038da45f057a7..8944726255c9c 100644 +--- a/arch/x86/xen/enlighten_pv.c ++++ b/arch/x86/xen/enlighten_pv.c +@@ -1266,6 +1266,8 @@ asmlinkage __visible void __init xen_start_kernel(struct start_info *si) + xen_vcpu_info_reset(0); + + x86_platform.get_nmi_reason = xen_get_nmi_reason; ++ x86_platform.realmode_reserve = x86_init_noop; ++ x86_platform.realmode_init = x86_init_noop; + + x86_init.resources.memory_setup = xen_memory_setup; + x86_init.irqs.intr_mode_select = x86_init_noop; +diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c +index c3e1f9a7d43aa..4b0d6fff88de5 100644 +--- a/arch/x86/xen/smp.c ++++ b/arch/x86/xen/smp.c +@@ -32,30 +32,30 @@ static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id) + + void xen_smp_intr_free(unsigned int cpu) + { ++ kfree(per_cpu(xen_resched_irq, cpu).name); ++ per_cpu(xen_resched_irq, cpu).name = NULL; + if (per_cpu(xen_resched_irq, cpu).irq >= 0) { + unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu).irq, NULL); + per_cpu(xen_resched_irq, cpu).irq = -1; +- kfree(per_cpu(xen_resched_irq, cpu).name); +- per_cpu(xen_resched_irq, cpu).name = NULL; + } ++ kfree(per_cpu(xen_callfunc_irq, cpu).name); ++ per_cpu(xen_callfunc_irq, cpu).name = NULL; + if (per_cpu(xen_callfunc_irq, cpu).irq >= 0) { + unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu).irq, NULL); + per_cpu(xen_callfunc_irq, cpu).irq = -1; +- kfree(per_cpu(xen_callfunc_irq, cpu).name); +- per_cpu(xen_callfunc_irq, cpu).name = NULL; + } ++ kfree(per_cpu(xen_debug_irq, cpu).name); ++ per_cpu(xen_debug_irq, cpu).name = NULL; + if (per_cpu(xen_debug_irq, cpu).irq >= 0) { + unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu).irq, NULL); + per_cpu(xen_debug_irq, cpu).irq = -1; +- kfree(per_cpu(xen_debug_irq, cpu).name); +- per_cpu(xen_debug_irq, cpu).name = NULL; + } ++ kfree(per_cpu(xen_callfuncsingle_irq, cpu).name); ++ per_cpu(xen_callfuncsingle_irq, cpu).name = NULL; + if (per_cpu(xen_callfuncsingle_irq, cpu).irq >= 0) { + unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu).irq, + NULL); + per_cpu(xen_callfuncsingle_irq, cpu).irq = -1; +- kfree(per_cpu(xen_callfuncsingle_irq, cpu).name); +- per_cpu(xen_callfuncsingle_irq, cpu).name = NULL; + } + } + +@@ -65,6 +65,7 @@ int xen_smp_intr_init(unsigned int cpu) + char *resched_name, *callfunc_name, *debug_name; + + resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu); ++ per_cpu(xen_resched_irq, cpu).name = resched_name; + rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR, + cpu, + xen_reschedule_interrupt, +@@ -74,9 +75,9 @@ int xen_smp_intr_init(unsigned int cpu) + if (rc < 0) + goto fail; + per_cpu(xen_resched_irq, cpu).irq = rc; +- per_cpu(xen_resched_irq, cpu).name = resched_name; + + callfunc_name = kasprintf(GFP_KERNEL, "callfunc%d", cpu); ++ per_cpu(xen_callfunc_irq, cpu).name = callfunc_name; + rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_VECTOR, + cpu, + xen_call_function_interrupt, +@@ -86,10 +87,10 @@ int xen_smp_intr_init(unsigned int cpu) + if (rc < 0) + goto fail; + per_cpu(xen_callfunc_irq, cpu).irq = rc; +- per_cpu(xen_callfunc_irq, cpu).name = callfunc_name; + + if (!xen_fifo_events) { + debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu); ++ per_cpu(xen_debug_irq, cpu).name = debug_name; + rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu, + xen_debug_interrupt, + IRQF_PERCPU | IRQF_NOBALANCING, +@@ -97,10 +98,10 @@ int xen_smp_intr_init(unsigned int cpu) + if (rc < 0) + goto fail; + per_cpu(xen_debug_irq, cpu).irq = rc; +- per_cpu(xen_debug_irq, cpu).name = debug_name; + } + + callfunc_name = kasprintf(GFP_KERNEL, "callfuncsingle%d", cpu); ++ per_cpu(xen_callfuncsingle_irq, cpu).name = callfunc_name; + rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_SINGLE_VECTOR, + cpu, + xen_call_function_single_interrupt, +@@ -110,7 +111,6 @@ int xen_smp_intr_init(unsigned int cpu) + if (rc < 0) + goto fail; + per_cpu(xen_callfuncsingle_irq, cpu).irq = rc; +- per_cpu(xen_callfuncsingle_irq, cpu).name = callfunc_name; + + return 0; + +diff --git a/arch/x86/xen/smp_pv.c b/arch/x86/xen/smp_pv.c +index 480be82e9b7be..6175f2c5c8224 100644 +--- a/arch/x86/xen/smp_pv.c ++++ b/arch/x86/xen/smp_pv.c +@@ -97,18 +97,18 @@ asmlinkage __visible void cpu_bringup_and_idle(void) + + void xen_smp_intr_free_pv(unsigned int cpu) + { ++ kfree(per_cpu(xen_irq_work, cpu).name); ++ per_cpu(xen_irq_work, cpu).name = NULL; + if (per_cpu(xen_irq_work, cpu).irq >= 0) { + unbind_from_irqhandler(per_cpu(xen_irq_work, cpu).irq, NULL); + per_cpu(xen_irq_work, cpu).irq = -1; +- kfree(per_cpu(xen_irq_work, cpu).name); +- per_cpu(xen_irq_work, cpu).name = NULL; + } + ++ kfree(per_cpu(xen_pmu_irq, cpu).name); ++ per_cpu(xen_pmu_irq, cpu).name = NULL; + if (per_cpu(xen_pmu_irq, cpu).irq >= 0) { + unbind_from_irqhandler(per_cpu(xen_pmu_irq, cpu).irq, NULL); + per_cpu(xen_pmu_irq, cpu).irq = -1; +- kfree(per_cpu(xen_pmu_irq, cpu).name); +- per_cpu(xen_pmu_irq, cpu).name = NULL; + } + } + +@@ -118,6 +118,7 @@ int xen_smp_intr_init_pv(unsigned int cpu) + char *callfunc_name, *pmu_name; + + callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu); ++ per_cpu(xen_irq_work, cpu).name = callfunc_name; + rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR, + cpu, + xen_irq_work_interrupt, +@@ -127,10 +128,10 @@ int xen_smp_intr_init_pv(unsigned int cpu) + if (rc < 0) + goto fail; + per_cpu(xen_irq_work, cpu).irq = rc; +- per_cpu(xen_irq_work, cpu).name = callfunc_name; + + if (is_xen_pmu) { + pmu_name = kasprintf(GFP_KERNEL, "pmu%d", cpu); ++ per_cpu(xen_pmu_irq, cpu).name = pmu_name; + rc = bind_virq_to_irqhandler(VIRQ_XENPMU, cpu, + xen_pmu_irq_handler, + IRQF_PERCPU|IRQF_NOBALANCING, +@@ -138,7 +139,6 @@ int xen_smp_intr_init_pv(unsigned int cpu) + if (rc < 0) + goto fail; + per_cpu(xen_pmu_irq, cpu).irq = rc; +- per_cpu(xen_pmu_irq, cpu).name = pmu_name; + } + + return 0; +diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c +index 043c73dfd2c98..5c6fc16e4b925 100644 +--- a/arch/x86/xen/spinlock.c ++++ b/arch/x86/xen/spinlock.c +@@ -75,6 +75,7 @@ void xen_init_lock_cpu(int cpu) + cpu, per_cpu(lock_kicker_irq, cpu)); + + name = kasprintf(GFP_KERNEL, "spinlock%d", cpu); ++ per_cpu(irq_name, cpu) = name; + irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR, + cpu, + dummy_handler, +@@ -85,7 +86,6 @@ void xen_init_lock_cpu(int cpu) + if (irq >= 0) { + disable_irq(irq); /* make sure it's never delivered */ + per_cpu(lock_kicker_irq, cpu) = irq; +- per_cpu(irq_name, cpu) = name; + } + + printk("cpu %d spinlock event irq %d\n", cpu, irq); +@@ -98,6 +98,8 @@ void xen_uninit_lock_cpu(int cpu) + if (!xen_pvspin) + return; + ++ kfree(per_cpu(irq_name, cpu)); ++ per_cpu(irq_name, cpu) = NULL; + /* + * When booting the kernel with 'mitigations=auto,nosmt', the secondary + * CPUs are not activated, and lock_kicker_irq is not initialized. +@@ -108,8 +110,6 @@ void xen_uninit_lock_cpu(int cpu) + + unbind_from_irqhandler(irq, NULL); + per_cpu(lock_kicker_irq, cpu) = -1; +- kfree(per_cpu(irq_name, cpu)); +- per_cpu(irq_name, cpu) = NULL; + } + + PV_CALLEE_SAVE_REGS_THUNK(xen_vcpu_stolen); +diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c +index 7ea427817f7f5..7b894df32e320 100644 +--- a/block/bfq-iosched.c ++++ b/block/bfq-iosched.c +@@ -386,6 +386,12 @@ static void bfq_put_stable_ref(struct bfq_queue *bfqq); + + void bic_set_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq, bool is_sync) + { ++ struct bfq_queue *old_bfqq = bic->bfqq[is_sync]; ++ ++ /* Clear bic pointer if bfqq is detached from this bic */ ++ if (old_bfqq && old_bfqq->bic == bic) ++ old_bfqq->bic = NULL; ++ + /* + * If bfqq != NULL, then a non-stable queue merge between + * bic->bfqq and bfqq is happening here. This causes troubles +@@ -5377,9 +5383,8 @@ static void bfq_exit_icq_bfqq(struct bfq_io_cq *bic, bool is_sync) + unsigned long flags; + + spin_lock_irqsave(&bfqd->lock, flags); +- bfqq->bic = NULL; +- bfq_exit_bfqq(bfqd, bfqq); + bic_set_bfqq(bic, NULL, is_sync); ++ bfq_exit_bfqq(bfqd, bfqq); + spin_unlock_irqrestore(&bfqd->lock, flags); + } + } +@@ -6784,6 +6789,12 @@ static struct bfq_queue *bfq_init_rq(struct request *rq) + bfqq = bfq_get_bfqq_handle_split(bfqd, bic, bio, + true, is_sync, + NULL); ++ if (unlikely(bfqq == &bfqd->oom_bfqq)) ++ bfqq_already_existing = true; ++ } else ++ bfqq_already_existing = true; ++ ++ if (!bfqq_already_existing) { + bfqq->waker_bfqq = old_bfqq->waker_bfqq; + bfqq->tentative_waker_bfqq = NULL; + +@@ -6797,8 +6808,7 @@ static struct bfq_queue *bfq_init_rq(struct request *rq) + if (bfqq->waker_bfqq) + hlist_add_head(&bfqq->woken_list_node, + &bfqq->waker_bfqq->woken_list); +- } else +- bfqq_already_existing = true; ++ } + } + } + +diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c +index ed761c62ad0a7..fcf9cf49f5de1 100644 +--- a/block/blk-cgroup.c ++++ b/block/blk-cgroup.c +@@ -33,6 +33,7 @@ + #include "blk-cgroup.h" + #include "blk-ioprio.h" + #include "blk-throttle.h" ++#include "blk-rq-qos.h" + + /* + * blkcg_pol_mutex protects blkcg_policy[] and policy [de]activation. +@@ -1275,6 +1276,7 @@ err_unlock: + void blkcg_exit_disk(struct gendisk *disk) + { + blkg_destroy_all(disk); ++ rq_qos_exit(disk->queue); + blk_throtl_exit(disk); + } + +diff --git a/block/blk-mq-sysfs.c b/block/blk-mq-sysfs.c +index 93997d297d427..4515288fbe351 100644 +--- a/block/blk-mq-sysfs.c ++++ b/block/blk-mq-sysfs.c +@@ -185,7 +185,7 @@ static int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx) + { + struct request_queue *q = hctx->queue; + struct blk_mq_ctx *ctx; +- int i, ret; ++ int i, j, ret; + + if (!hctx->nr_ctx) + return 0; +@@ -197,9 +197,16 @@ static int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx) + hctx_for_each_ctx(hctx, ctx, i) { + ret = kobject_add(&ctx->kobj, &hctx->kobj, "cpu%u", ctx->cpu); + if (ret) +- break; ++ goto out; + } + ++ return 0; ++out: ++ hctx_for_each_ctx(hctx, ctx, j) { ++ if (j < i) ++ kobject_del(&ctx->kobj); ++ } ++ kobject_del(&hctx->kobj); + return ret; + } + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 228a6696d8351..0b855e033a834 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -1529,7 +1529,13 @@ static void blk_mq_rq_timed_out(struct request *req) + blk_add_timer(req); + } + +-static bool blk_mq_req_expired(struct request *rq, unsigned long *next) ++struct blk_expired_data { ++ bool has_timedout_rq; ++ unsigned long next; ++ unsigned long timeout_start; ++}; ++ ++static bool blk_mq_req_expired(struct request *rq, struct blk_expired_data *expired) + { + unsigned long deadline; + +@@ -1539,13 +1545,13 @@ static bool blk_mq_req_expired(struct request *rq, unsigned long *next) + return false; + + deadline = READ_ONCE(rq->deadline); +- if (time_after_eq(jiffies, deadline)) ++ if (time_after_eq(expired->timeout_start, deadline)) + return true; + +- if (*next == 0) +- *next = deadline; +- else if (time_after(*next, deadline)) +- *next = deadline; ++ if (expired->next == 0) ++ expired->next = deadline; ++ else if (time_after(expired->next, deadline)) ++ expired->next = deadline; + return false; + } + +@@ -1561,7 +1567,7 @@ void blk_mq_put_rq_ref(struct request *rq) + + static bool blk_mq_check_expired(struct request *rq, void *priv) + { +- unsigned long *next = priv; ++ struct blk_expired_data *expired = priv; + + /* + * blk_mq_queue_tag_busy_iter() has locked the request, so it cannot +@@ -1570,7 +1576,18 @@ static bool blk_mq_check_expired(struct request *rq, void *priv) + * it was completed and reallocated as a new request after returning + * from blk_mq_check_expired(). + */ +- if (blk_mq_req_expired(rq, next)) ++ if (blk_mq_req_expired(rq, expired)) { ++ expired->has_timedout_rq = true; ++ return false; ++ } ++ return true; ++} ++ ++static bool blk_mq_handle_expired(struct request *rq, void *priv) ++{ ++ struct blk_expired_data *expired = priv; ++ ++ if (blk_mq_req_expired(rq, expired)) + blk_mq_rq_timed_out(rq); + return true; + } +@@ -1579,7 +1596,9 @@ static void blk_mq_timeout_work(struct work_struct *work) + { + struct request_queue *q = + container_of(work, struct request_queue, timeout_work); +- unsigned long next = 0; ++ struct blk_expired_data expired = { ++ .timeout_start = jiffies, ++ }; + struct blk_mq_hw_ctx *hctx; + unsigned long i; + +@@ -1599,10 +1618,23 @@ static void blk_mq_timeout_work(struct work_struct *work) + if (!percpu_ref_tryget(&q->q_usage_counter)) + return; + +- blk_mq_queue_tag_busy_iter(q, blk_mq_check_expired, &next); ++ /* check if there is any timed-out request */ ++ blk_mq_queue_tag_busy_iter(q, blk_mq_check_expired, &expired); ++ if (expired.has_timedout_rq) { ++ /* ++ * Before walking tags, we must ensure any submit started ++ * before the current time has finished. Since the submit ++ * uses srcu or rcu, wait for a synchronization point to ++ * ensure all running submits have finished ++ */ ++ blk_mq_wait_quiesce_done(q); ++ ++ expired.next = 0; ++ blk_mq_queue_tag_busy_iter(q, blk_mq_handle_expired, &expired); ++ } + +- if (next != 0) { +- mod_timer(&q->timeout, next); ++ if (expired.next != 0) { ++ mod_timer(&q->timeout, expired.next); + } else { + /* + * Request timeouts are handled as a forward rolling timer. If +diff --git a/block/blk.h b/block/blk.h +index a186ea20f39d8..8b75a95b28d60 100644 +--- a/block/blk.h ++++ b/block/blk.h +@@ -436,7 +436,7 @@ static inline struct kmem_cache *blk_get_queue_kmem_cache(bool srcu) + } + struct request_queue *blk_alloc_queue(int node_id, bool alloc_srcu); + +-int disk_scan_partitions(struct gendisk *disk, fmode_t mode); ++int disk_scan_partitions(struct gendisk *disk, fmode_t mode, void *owner); + + int disk_alloc_events(struct gendisk *disk); + void disk_add_events(struct gendisk *disk); +diff --git a/block/genhd.c b/block/genhd.c +index 0f9769db2de83..c4765681a8b4b 100644 +--- a/block/genhd.c ++++ b/block/genhd.c +@@ -356,7 +356,7 @@ void disk_uevent(struct gendisk *disk, enum kobject_action action) + } + EXPORT_SYMBOL_GPL(disk_uevent); + +-int disk_scan_partitions(struct gendisk *disk, fmode_t mode) ++int disk_scan_partitions(struct gendisk *disk, fmode_t mode, void *owner) + { + struct block_device *bdev; + +@@ -366,6 +366,9 @@ int disk_scan_partitions(struct gendisk *disk, fmode_t mode) + return -EINVAL; + if (disk->open_partitions) + return -EBUSY; ++ /* Someone else has bdev exclusively open? */ ++ if (disk->part0->bd_holder && disk->part0->bd_holder != owner) ++ return -EBUSY; + + set_bit(GD_NEED_PART_SCAN, &disk->state); + bdev = blkdev_get_by_dev(disk_devt(disk), mode, NULL); +@@ -500,7 +503,7 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk, + + bdev_add(disk->part0, ddev->devt); + if (get_capacity(disk)) +- disk_scan_partitions(disk, FMODE_READ); ++ disk_scan_partitions(disk, FMODE_READ, NULL); + + /* + * Announce the disk and partitions after all partitions are +@@ -530,6 +533,7 @@ out_unregister_queue: + rq_qos_exit(disk->queue); + out_put_slave_dir: + kobject_put(disk->slave_dir); ++ disk->slave_dir = NULL; + out_put_holder_dir: + kobject_put(disk->part0->bd_holder_dir); + out_del_integrity: +@@ -629,6 +633,7 @@ void del_gendisk(struct gendisk *disk) + + kobject_put(disk->part0->bd_holder_dir); + kobject_put(disk->slave_dir); ++ disk->slave_dir = NULL; + + part_stat_set_all(disk->part0, 0); + disk->part0->bd_stamp = 0; +diff --git a/block/ioctl.c b/block/ioctl.c +index 60121e89052bc..96617512982e5 100644 +--- a/block/ioctl.c ++++ b/block/ioctl.c +@@ -467,9 +467,10 @@ static int blkdev_bszset(struct block_device *bdev, fmode_t mode, + * user space. Note the separate arg/argp parameters that are needed + * to deal with the compat_ptr() conversion. + */ +-static int blkdev_common_ioctl(struct block_device *bdev, fmode_t mode, +- unsigned cmd, unsigned long arg, void __user *argp) ++static int blkdev_common_ioctl(struct file *file, fmode_t mode, unsigned cmd, ++ unsigned long arg, void __user *argp) + { ++ struct block_device *bdev = I_BDEV(file->f_mapping->host); + unsigned int max_sectors; + + switch (cmd) { +@@ -527,7 +528,8 @@ static int blkdev_common_ioctl(struct block_device *bdev, fmode_t mode, + return -EACCES; + if (bdev_is_partition(bdev)) + return -EINVAL; +- return disk_scan_partitions(bdev->bd_disk, mode & ~FMODE_EXCL); ++ return disk_scan_partitions(bdev->bd_disk, mode & ~FMODE_EXCL, ++ file); + case BLKTRACESTART: + case BLKTRACESTOP: + case BLKTRACETEARDOWN: +@@ -605,7 +607,7 @@ long blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) + break; + } + +- ret = blkdev_common_ioctl(bdev, mode, cmd, arg, argp); ++ ret = blkdev_common_ioctl(file, mode, cmd, arg, argp); + if (ret != -ENOIOCTLCMD) + return ret; + +@@ -674,7 +676,7 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) + break; + } + +- ret = blkdev_common_ioctl(bdev, mode, cmd, arg, argp); ++ ret = blkdev_common_ioctl(file, mode, cmd, arg, argp); + if (ret == -ENOIOCTLCMD && disk->fops->compat_ioctl) + ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg); + +diff --git a/crypto/cryptd.c b/crypto/cryptd.c +index 668095eca0faf..ca3a40fc7da91 100644 +--- a/crypto/cryptd.c ++++ b/crypto/cryptd.c +@@ -68,11 +68,12 @@ struct aead_instance_ctx { + + struct cryptd_skcipher_ctx { + refcount_t refcnt; +- struct crypto_sync_skcipher *child; ++ struct crypto_skcipher *child; + }; + + struct cryptd_skcipher_request_ctx { + crypto_completion_t complete; ++ struct skcipher_request req; + }; + + struct cryptd_hash_ctx { +@@ -227,13 +228,13 @@ static int cryptd_skcipher_setkey(struct crypto_skcipher *parent, + const u8 *key, unsigned int keylen) + { + struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(parent); +- struct crypto_sync_skcipher *child = ctx->child; ++ struct crypto_skcipher *child = ctx->child; + +- crypto_sync_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); +- crypto_sync_skcipher_set_flags(child, +- crypto_skcipher_get_flags(parent) & +- CRYPTO_TFM_REQ_MASK); +- return crypto_sync_skcipher_setkey(child, key, keylen); ++ crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); ++ crypto_skcipher_set_flags(child, ++ crypto_skcipher_get_flags(parent) & ++ CRYPTO_TFM_REQ_MASK); ++ return crypto_skcipher_setkey(child, key, keylen); + } + + static void cryptd_skcipher_complete(struct skcipher_request *req, int err) +@@ -258,13 +259,13 @@ static void cryptd_skcipher_encrypt(struct crypto_async_request *base, + struct cryptd_skcipher_request_ctx *rctx = skcipher_request_ctx(req); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm); +- struct crypto_sync_skcipher *child = ctx->child; +- SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, child); ++ struct skcipher_request *subreq = &rctx->req; ++ struct crypto_skcipher *child = ctx->child; + + if (unlikely(err == -EINPROGRESS)) + goto out; + +- skcipher_request_set_sync_tfm(subreq, child); ++ skcipher_request_set_tfm(subreq, child); + skcipher_request_set_callback(subreq, CRYPTO_TFM_REQ_MAY_SLEEP, + NULL, NULL); + skcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, +@@ -286,13 +287,13 @@ static void cryptd_skcipher_decrypt(struct crypto_async_request *base, + struct cryptd_skcipher_request_ctx *rctx = skcipher_request_ctx(req); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm); +- struct crypto_sync_skcipher *child = ctx->child; +- SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, child); ++ struct skcipher_request *subreq = &rctx->req; ++ struct crypto_skcipher *child = ctx->child; + + if (unlikely(err == -EINPROGRESS)) + goto out; + +- skcipher_request_set_sync_tfm(subreq, child); ++ skcipher_request_set_tfm(subreq, child); + skcipher_request_set_callback(subreq, CRYPTO_TFM_REQ_MAY_SLEEP, + NULL, NULL); + skcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, +@@ -343,9 +344,10 @@ static int cryptd_skcipher_init_tfm(struct crypto_skcipher *tfm) + if (IS_ERR(cipher)) + return PTR_ERR(cipher); + +- ctx->child = (struct crypto_sync_skcipher *)cipher; ++ ctx->child = cipher; + crypto_skcipher_set_reqsize( +- tfm, sizeof(struct cryptd_skcipher_request_ctx)); ++ tfm, sizeof(struct cryptd_skcipher_request_ctx) + ++ crypto_skcipher_reqsize(cipher)); + return 0; + } + +@@ -353,7 +355,7 @@ static void cryptd_skcipher_exit_tfm(struct crypto_skcipher *tfm) + { + struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm); + +- crypto_free_sync_skcipher(ctx->child); ++ crypto_free_skcipher(ctx->child); + } + + static void cryptd_skcipher_free(struct skcipher_instance *inst) +@@ -931,7 +933,7 @@ struct crypto_skcipher *cryptd_skcipher_child(struct cryptd_skcipher *tfm) + { + struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(&tfm->base); + +- return &ctx->child->base; ++ return ctx->child; + } + EXPORT_SYMBOL_GPL(cryptd_skcipher_child); + +diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c +index a82679b576bb4..b23235d58a122 100644 +--- a/crypto/tcrypt.c ++++ b/crypto/tcrypt.c +@@ -1090,15 +1090,6 @@ static void test_mb_skcipher_speed(const char *algo, int enc, int secs, + goto out_free_tfm; + } + +- +- for (i = 0; i < num_mb; ++i) +- if (testmgr_alloc_buf(data[i].xbuf)) { +- while (i--) +- testmgr_free_buf(data[i].xbuf); +- goto out_free_tfm; +- } +- +- + for (i = 0; i < num_mb; ++i) { + data[i].req = skcipher_request_alloc(tfm, GFP_KERNEL); + if (!data[i].req) { +@@ -1471,387 +1462,387 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb) + } + + for (i = 1; i < 200; i++) +- ret += do_test(NULL, 0, 0, i, num_mb); ++ ret = min(ret, do_test(NULL, 0, 0, i, num_mb)); + break; + + case 1: +- ret += tcrypt_test("md5"); ++ ret = min(ret, tcrypt_test("md5")); + break; + + case 2: +- ret += tcrypt_test("sha1"); ++ ret = min(ret, tcrypt_test("sha1")); + break; + + case 3: +- ret += tcrypt_test("ecb(des)"); +- ret += tcrypt_test("cbc(des)"); +- ret += tcrypt_test("ctr(des)"); ++ ret = min(ret, tcrypt_test("ecb(des)")); ++ ret = min(ret, tcrypt_test("cbc(des)")); ++ ret = min(ret, tcrypt_test("ctr(des)")); + break; + + case 4: +- ret += tcrypt_test("ecb(des3_ede)"); +- ret += tcrypt_test("cbc(des3_ede)"); +- ret += tcrypt_test("ctr(des3_ede)"); ++ ret = min(ret, tcrypt_test("ecb(des3_ede)")); ++ ret = min(ret, tcrypt_test("cbc(des3_ede)")); ++ ret = min(ret, tcrypt_test("ctr(des3_ede)")); + break; + + case 5: +- ret += tcrypt_test("md4"); ++ ret = min(ret, tcrypt_test("md4")); + break; + + case 6: +- ret += tcrypt_test("sha256"); ++ ret = min(ret, tcrypt_test("sha256")); + break; + + case 7: +- ret += tcrypt_test("ecb(blowfish)"); +- ret += tcrypt_test("cbc(blowfish)"); +- ret += tcrypt_test("ctr(blowfish)"); ++ ret = min(ret, tcrypt_test("ecb(blowfish)")); ++ ret = min(ret, tcrypt_test("cbc(blowfish)")); ++ ret = min(ret, tcrypt_test("ctr(blowfish)")); + break; + + case 8: +- ret += tcrypt_test("ecb(twofish)"); +- ret += tcrypt_test("cbc(twofish)"); +- ret += tcrypt_test("ctr(twofish)"); +- ret += tcrypt_test("lrw(twofish)"); +- ret += tcrypt_test("xts(twofish)"); ++ ret = min(ret, tcrypt_test("ecb(twofish)")); ++ ret = min(ret, tcrypt_test("cbc(twofish)")); ++ ret = min(ret, tcrypt_test("ctr(twofish)")); ++ ret = min(ret, tcrypt_test("lrw(twofish)")); ++ ret = min(ret, tcrypt_test("xts(twofish)")); + break; + + case 9: +- ret += tcrypt_test("ecb(serpent)"); +- ret += tcrypt_test("cbc(serpent)"); +- ret += tcrypt_test("ctr(serpent)"); +- ret += tcrypt_test("lrw(serpent)"); +- ret += tcrypt_test("xts(serpent)"); ++ ret = min(ret, tcrypt_test("ecb(serpent)")); ++ ret = min(ret, tcrypt_test("cbc(serpent)")); ++ ret = min(ret, tcrypt_test("ctr(serpent)")); ++ ret = min(ret, tcrypt_test("lrw(serpent)")); ++ ret = min(ret, tcrypt_test("xts(serpent)")); + break; + + case 10: +- ret += tcrypt_test("ecb(aes)"); +- ret += tcrypt_test("cbc(aes)"); +- ret += tcrypt_test("lrw(aes)"); +- ret += tcrypt_test("xts(aes)"); +- ret += tcrypt_test("ctr(aes)"); +- ret += tcrypt_test("rfc3686(ctr(aes))"); +- ret += tcrypt_test("ofb(aes)"); +- ret += tcrypt_test("cfb(aes)"); +- ret += tcrypt_test("xctr(aes)"); ++ ret = min(ret, tcrypt_test("ecb(aes)")); ++ ret = min(ret, tcrypt_test("cbc(aes)")); ++ ret = min(ret, tcrypt_test("lrw(aes)")); ++ ret = min(ret, tcrypt_test("xts(aes)")); ++ ret = min(ret, tcrypt_test("ctr(aes)")); ++ ret = min(ret, tcrypt_test("rfc3686(ctr(aes))")); ++ ret = min(ret, tcrypt_test("ofb(aes)")); ++ ret = min(ret, tcrypt_test("cfb(aes)")); ++ ret = min(ret, tcrypt_test("xctr(aes)")); + break; + + case 11: +- ret += tcrypt_test("sha384"); ++ ret = min(ret, tcrypt_test("sha384")); + break; + + case 12: +- ret += tcrypt_test("sha512"); ++ ret = min(ret, tcrypt_test("sha512")); + break; + + case 13: +- ret += tcrypt_test("deflate"); ++ ret = min(ret, tcrypt_test("deflate")); + break; + + case 14: +- ret += tcrypt_test("ecb(cast5)"); +- ret += tcrypt_test("cbc(cast5)"); +- ret += tcrypt_test("ctr(cast5)"); ++ ret = min(ret, tcrypt_test("ecb(cast5)")); ++ ret = min(ret, tcrypt_test("cbc(cast5)")); ++ ret = min(ret, tcrypt_test("ctr(cast5)")); + break; + + case 15: +- ret += tcrypt_test("ecb(cast6)"); +- ret += tcrypt_test("cbc(cast6)"); +- ret += tcrypt_test("ctr(cast6)"); +- ret += tcrypt_test("lrw(cast6)"); +- ret += tcrypt_test("xts(cast6)"); ++ ret = min(ret, tcrypt_test("ecb(cast6)")); ++ ret = min(ret, tcrypt_test("cbc(cast6)")); ++ ret = min(ret, tcrypt_test("ctr(cast6)")); ++ ret = min(ret, tcrypt_test("lrw(cast6)")); ++ ret = min(ret, tcrypt_test("xts(cast6)")); + break; + + case 16: +- ret += tcrypt_test("ecb(arc4)"); ++ ret = min(ret, tcrypt_test("ecb(arc4)")); + break; + + case 17: +- ret += tcrypt_test("michael_mic"); ++ ret = min(ret, tcrypt_test("michael_mic")); + break; + + case 18: +- ret += tcrypt_test("crc32c"); ++ ret = min(ret, tcrypt_test("crc32c")); + break; + + case 19: +- ret += tcrypt_test("ecb(tea)"); ++ ret = min(ret, tcrypt_test("ecb(tea)")); + break; + + case 20: +- ret += tcrypt_test("ecb(xtea)"); ++ ret = min(ret, tcrypt_test("ecb(xtea)")); + break; + + case 21: +- ret += tcrypt_test("ecb(khazad)"); ++ ret = min(ret, tcrypt_test("ecb(khazad)")); + break; + + case 22: +- ret += tcrypt_test("wp512"); ++ ret = min(ret, tcrypt_test("wp512")); + break; + + case 23: +- ret += tcrypt_test("wp384"); ++ ret = min(ret, tcrypt_test("wp384")); + break; + + case 24: +- ret += tcrypt_test("wp256"); ++ ret = min(ret, tcrypt_test("wp256")); + break; + + case 26: +- ret += tcrypt_test("ecb(anubis)"); +- ret += tcrypt_test("cbc(anubis)"); ++ ret = min(ret, tcrypt_test("ecb(anubis)")); ++ ret = min(ret, tcrypt_test("cbc(anubis)")); + break; + + case 30: +- ret += tcrypt_test("ecb(xeta)"); ++ ret = min(ret, tcrypt_test("ecb(xeta)")); + break; + + case 31: +- ret += tcrypt_test("pcbc(fcrypt)"); ++ ret = min(ret, tcrypt_test("pcbc(fcrypt)")); + break; + + case 32: +- ret += tcrypt_test("ecb(camellia)"); +- ret += tcrypt_test("cbc(camellia)"); +- ret += tcrypt_test("ctr(camellia)"); +- ret += tcrypt_test("lrw(camellia)"); +- ret += tcrypt_test("xts(camellia)"); ++ ret = min(ret, tcrypt_test("ecb(camellia)")); ++ ret = min(ret, tcrypt_test("cbc(camellia)")); ++ ret = min(ret, tcrypt_test("ctr(camellia)")); ++ ret = min(ret, tcrypt_test("lrw(camellia)")); ++ ret = min(ret, tcrypt_test("xts(camellia)")); + break; + + case 33: +- ret += tcrypt_test("sha224"); ++ ret = min(ret, tcrypt_test("sha224")); + break; + + case 35: +- ret += tcrypt_test("gcm(aes)"); ++ ret = min(ret, tcrypt_test("gcm(aes)")); + break; + + case 36: +- ret += tcrypt_test("lzo"); ++ ret = min(ret, tcrypt_test("lzo")); + break; + + case 37: +- ret += tcrypt_test("ccm(aes)"); ++ ret = min(ret, tcrypt_test("ccm(aes)")); + break; + + case 38: +- ret += tcrypt_test("cts(cbc(aes))"); ++ ret = min(ret, tcrypt_test("cts(cbc(aes))")); + break; + + case 39: +- ret += tcrypt_test("xxhash64"); ++ ret = min(ret, tcrypt_test("xxhash64")); + break; + + case 40: +- ret += tcrypt_test("rmd160"); ++ ret = min(ret, tcrypt_test("rmd160")); + break; + + case 42: +- ret += tcrypt_test("blake2b-512"); ++ ret = min(ret, tcrypt_test("blake2b-512")); + break; + + case 43: +- ret += tcrypt_test("ecb(seed)"); ++ ret = min(ret, tcrypt_test("ecb(seed)")); + break; + + case 45: +- ret += tcrypt_test("rfc4309(ccm(aes))"); ++ ret = min(ret, tcrypt_test("rfc4309(ccm(aes))")); + break; + + case 46: +- ret += tcrypt_test("ghash"); ++ ret = min(ret, tcrypt_test("ghash")); + break; + + case 47: +- ret += tcrypt_test("crct10dif"); ++ ret = min(ret, tcrypt_test("crct10dif")); + break; + + case 48: +- ret += tcrypt_test("sha3-224"); ++ ret = min(ret, tcrypt_test("sha3-224")); + break; + + case 49: +- ret += tcrypt_test("sha3-256"); ++ ret = min(ret, tcrypt_test("sha3-256")); + break; + + case 50: +- ret += tcrypt_test("sha3-384"); ++ ret = min(ret, tcrypt_test("sha3-384")); + break; + + case 51: +- ret += tcrypt_test("sha3-512"); ++ ret = min(ret, tcrypt_test("sha3-512")); + break; + + case 52: +- ret += tcrypt_test("sm3"); ++ ret = min(ret, tcrypt_test("sm3")); + break; + + case 53: +- ret += tcrypt_test("streebog256"); ++ ret = min(ret, tcrypt_test("streebog256")); + break; + + case 54: +- ret += tcrypt_test("streebog512"); ++ ret = min(ret, tcrypt_test("streebog512")); + break; + + case 55: +- ret += tcrypt_test("gcm(sm4)"); ++ ret = min(ret, tcrypt_test("gcm(sm4)")); + break; + + case 56: +- ret += tcrypt_test("ccm(sm4)"); ++ ret = min(ret, tcrypt_test("ccm(sm4)")); + break; + + case 57: +- ret += tcrypt_test("polyval"); ++ ret = min(ret, tcrypt_test("polyval")); + break; + + case 58: +- ret += tcrypt_test("gcm(aria)"); ++ ret = min(ret, tcrypt_test("gcm(aria)")); + break; + + case 100: +- ret += tcrypt_test("hmac(md5)"); ++ ret = min(ret, tcrypt_test("hmac(md5)")); + break; + + case 101: +- ret += tcrypt_test("hmac(sha1)"); ++ ret = min(ret, tcrypt_test("hmac(sha1)")); + break; + + case 102: +- ret += tcrypt_test("hmac(sha256)"); ++ ret = min(ret, tcrypt_test("hmac(sha256)")); + break; + + case 103: +- ret += tcrypt_test("hmac(sha384)"); ++ ret = min(ret, tcrypt_test("hmac(sha384)")); + break; + + case 104: +- ret += tcrypt_test("hmac(sha512)"); ++ ret = min(ret, tcrypt_test("hmac(sha512)")); + break; + + case 105: +- ret += tcrypt_test("hmac(sha224)"); ++ ret = min(ret, tcrypt_test("hmac(sha224)")); + break; + + case 106: +- ret += tcrypt_test("xcbc(aes)"); ++ ret = min(ret, tcrypt_test("xcbc(aes)")); + break; + + case 108: +- ret += tcrypt_test("hmac(rmd160)"); ++ ret = min(ret, tcrypt_test("hmac(rmd160)")); + break; + + case 109: +- ret += tcrypt_test("vmac64(aes)"); ++ ret = min(ret, tcrypt_test("vmac64(aes)")); + break; + + case 111: +- ret += tcrypt_test("hmac(sha3-224)"); ++ ret = min(ret, tcrypt_test("hmac(sha3-224)")); + break; + + case 112: +- ret += tcrypt_test("hmac(sha3-256)"); ++ ret = min(ret, tcrypt_test("hmac(sha3-256)")); + break; + + case 113: +- ret += tcrypt_test("hmac(sha3-384)"); ++ ret = min(ret, tcrypt_test("hmac(sha3-384)")); + break; + + case 114: +- ret += tcrypt_test("hmac(sha3-512)"); ++ ret = min(ret, tcrypt_test("hmac(sha3-512)")); + break; + + case 115: +- ret += tcrypt_test("hmac(streebog256)"); ++ ret = min(ret, tcrypt_test("hmac(streebog256)")); + break; + + case 116: +- ret += tcrypt_test("hmac(streebog512)"); ++ ret = min(ret, tcrypt_test("hmac(streebog512)")); + break; + + case 150: +- ret += tcrypt_test("ansi_cprng"); ++ ret = min(ret, tcrypt_test("ansi_cprng")); + break; + + case 151: +- ret += tcrypt_test("rfc4106(gcm(aes))"); ++ ret = min(ret, tcrypt_test("rfc4106(gcm(aes))")); + break; + + case 152: +- ret += tcrypt_test("rfc4543(gcm(aes))"); ++ ret = min(ret, tcrypt_test("rfc4543(gcm(aes))")); + break; + + case 153: +- ret += tcrypt_test("cmac(aes)"); ++ ret = min(ret, tcrypt_test("cmac(aes)")); + break; + + case 154: +- ret += tcrypt_test("cmac(des3_ede)"); ++ ret = min(ret, tcrypt_test("cmac(des3_ede)")); + break; + + case 155: +- ret += tcrypt_test("authenc(hmac(sha1),cbc(aes))"); ++ ret = min(ret, tcrypt_test("authenc(hmac(sha1),cbc(aes))")); + break; + + case 156: +- ret += tcrypt_test("authenc(hmac(md5),ecb(cipher_null))"); ++ ret = min(ret, tcrypt_test("authenc(hmac(md5),ecb(cipher_null))")); + break; + + case 157: +- ret += tcrypt_test("authenc(hmac(sha1),ecb(cipher_null))"); ++ ret = min(ret, tcrypt_test("authenc(hmac(sha1),ecb(cipher_null))")); + break; + + case 158: +- ret += tcrypt_test("cbcmac(sm4)"); ++ ret = min(ret, tcrypt_test("cbcmac(sm4)")); + break; + + case 159: +- ret += tcrypt_test("cmac(sm4)"); ++ ret = min(ret, tcrypt_test("cmac(sm4)")); + break; + + case 181: +- ret += tcrypt_test("authenc(hmac(sha1),cbc(des))"); ++ ret = min(ret, tcrypt_test("authenc(hmac(sha1),cbc(des))")); + break; + case 182: +- ret += tcrypt_test("authenc(hmac(sha1),cbc(des3_ede))"); ++ ret = min(ret, tcrypt_test("authenc(hmac(sha1),cbc(des3_ede))")); + break; + case 183: +- ret += tcrypt_test("authenc(hmac(sha224),cbc(des))"); ++ ret = min(ret, tcrypt_test("authenc(hmac(sha224),cbc(des))")); + break; + case 184: +- ret += tcrypt_test("authenc(hmac(sha224),cbc(des3_ede))"); ++ ret = min(ret, tcrypt_test("authenc(hmac(sha224),cbc(des3_ede))")); + break; + case 185: +- ret += tcrypt_test("authenc(hmac(sha256),cbc(des))"); ++ ret = min(ret, tcrypt_test("authenc(hmac(sha256),cbc(des))")); + break; + case 186: +- ret += tcrypt_test("authenc(hmac(sha256),cbc(des3_ede))"); ++ ret = min(ret, tcrypt_test("authenc(hmac(sha256),cbc(des3_ede))")); + break; + case 187: +- ret += tcrypt_test("authenc(hmac(sha384),cbc(des))"); ++ ret = min(ret, tcrypt_test("authenc(hmac(sha384),cbc(des))")); + break; + case 188: +- ret += tcrypt_test("authenc(hmac(sha384),cbc(des3_ede))"); ++ ret = min(ret, tcrypt_test("authenc(hmac(sha384),cbc(des3_ede))")); + break; + case 189: +- ret += tcrypt_test("authenc(hmac(sha512),cbc(des))"); ++ ret = min(ret, tcrypt_test("authenc(hmac(sha512),cbc(des))")); + break; + case 190: +- ret += tcrypt_test("authenc(hmac(sha512),cbc(des3_ede))"); ++ ret = min(ret, tcrypt_test("authenc(hmac(sha512),cbc(des3_ede))")); + break; + case 191: +- ret += tcrypt_test("ecb(sm4)"); +- ret += tcrypt_test("cbc(sm4)"); +- ret += tcrypt_test("cfb(sm4)"); +- ret += tcrypt_test("ctr(sm4)"); ++ ret = min(ret, tcrypt_test("ecb(sm4)")); ++ ret = min(ret, tcrypt_test("cbc(sm4)")); ++ ret = min(ret, tcrypt_test("cfb(sm4)")); ++ ret = min(ret, tcrypt_test("ctr(sm4)")); + break; + case 192: +- ret += tcrypt_test("ecb(aria)"); +- ret += tcrypt_test("cbc(aria)"); +- ret += tcrypt_test("cfb(aria)"); +- ret += tcrypt_test("ctr(aria)"); ++ ret = min(ret, tcrypt_test("ecb(aria)")); ++ ret = min(ret, tcrypt_test("cbc(aria)")); ++ ret = min(ret, tcrypt_test("cfb(aria)")); ++ ret = min(ret, tcrypt_test("ctr(aria)")); + break; + case 200: + test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0, +diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c +index ae2e768830bfc..9332bc688713c 100644 +--- a/drivers/acpi/acpica/dsmethod.c ++++ b/drivers/acpi/acpica/dsmethod.c +@@ -517,7 +517,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + status = AE_NO_MEMORY; +- goto cleanup; ++ goto pop_walk_state; + } + + info->parameters = &this_walk_state->operands[0]; +@@ -529,7 +529,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, + + ACPI_FREE(info); + if (ACPI_FAILURE(status)) { +- goto cleanup; ++ goto pop_walk_state; + } + + next_walk_state->method_nesting_depth = +@@ -575,6 +575,12 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, + + return_ACPI_STATUS(status); + ++pop_walk_state: ++ ++ /* On error, pop the walk state to be deleted from thread */ ++ ++ acpi_ds_pop_walk_state(thread); ++ + cleanup: + + /* On error, we must terminate the method properly */ +diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c +index 400b9e15a709c..63c17f420fb86 100644 +--- a/drivers/acpi/acpica/utcopy.c ++++ b/drivers/acpi/acpica/utcopy.c +@@ -916,13 +916,6 @@ acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj, + status = acpi_ut_walk_package_tree(source_obj, dest_obj, + acpi_ut_copy_ielement_to_ielement, + walk_state); +- if (ACPI_FAILURE(status)) { +- +- /* On failure, delete the destination package object */ +- +- acpi_ut_remove_reference(dest_obj); +- } +- + return_ACPI_STATUS(status); + } + +diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c +index 9b42628cf21b3..9751b84c1b221 100644 +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -1875,6 +1875,16 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Gaming Laptop 15-cx0xxx"), + }, + }, ++ { ++ /* ++ * HP Pavilion Gaming Laptop 15-cx0041ur ++ */ ++ .callback = ec_honor_dsdt_gpe, ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "HP"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "HP 15-cx0041ur"), ++ }, ++ }, + { + /* + * Samsung hardware +diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c +index 1cc4647f78b86..c2c786eb95abc 100644 +--- a/drivers/acpi/irq.c ++++ b/drivers/acpi/irq.c +@@ -94,6 +94,7 @@ EXPORT_SYMBOL_GPL(acpi_unregister_gsi); + /** + * acpi_get_irq_source_fwhandle() - Retrieve fwhandle from IRQ resource source. + * @source: acpi_resource_source to use for the lookup. ++ * @gsi: GSI IRQ number + * + * Description: + * Retrieve the fwhandle of the device referenced by the given IRQ resource +@@ -297,8 +298,8 @@ EXPORT_SYMBOL_GPL(acpi_irq_get); + /** + * acpi_set_irq_model - Setup the GSI irqdomain information + * @model: the value assigned to acpi_irq_model +- * @fwnode: the irq_domain identifier for mapping and looking up +- * GSI interrupts ++ * @fn: a dispatcher function that will return the domain fwnode ++ * for a given GSI + */ + void __init acpi_set_irq_model(enum acpi_irq_model_id model, + struct fwnode_handle *(*fn)(u32)) +diff --git a/drivers/acpi/pfr_telemetry.c b/drivers/acpi/pfr_telemetry.c +index 9abf350bd7a5a..27fb6cdad75f9 100644 +--- a/drivers/acpi/pfr_telemetry.c ++++ b/drivers/acpi/pfr_telemetry.c +@@ -144,7 +144,7 @@ static int get_pfrt_log_data_info(struct pfrt_log_data_info *data_info, + ret = 0; + + free_acpi_buffer: +- kfree(out_obj); ++ ACPI_FREE(out_obj); + + return ret; + } +@@ -180,7 +180,7 @@ static int set_pfrt_log_level(int level, struct pfrt_log_device *pfrt_log_dev) + ret = -EBUSY; + } + +- kfree(out_obj); ++ ACPI_FREE(out_obj); + + return ret; + } +@@ -218,7 +218,7 @@ static int get_pfrt_log_level(struct pfrt_log_device *pfrt_log_dev) + ret = obj->integer.value; + + free_acpi_buffer: +- kfree(out_obj); ++ ACPI_FREE(out_obj); + + return ret; + } +diff --git a/drivers/acpi/pfr_update.c b/drivers/acpi/pfr_update.c +index 6bb0b778b5da5..9d2bdc13253a5 100644 +--- a/drivers/acpi/pfr_update.c ++++ b/drivers/acpi/pfr_update.c +@@ -178,7 +178,7 @@ static int query_capability(struct pfru_update_cap_info *cap_hdr, + ret = 0; + + free_acpi_buffer: +- kfree(out_obj); ++ ACPI_FREE(out_obj); + + return ret; + } +@@ -224,7 +224,7 @@ static int query_buffer(struct pfru_com_buf_info *info, + ret = 0; + + free_acpi_buffer: +- kfree(out_obj); ++ ACPI_FREE(out_obj); + + return ret; + } +@@ -385,7 +385,7 @@ static int start_update(int action, struct pfru_device *pfru_dev) + ret = 0; + + free_acpi_buffer: +- kfree(out_obj); ++ ACPI_FREE(out_obj); + + return ret; + } +diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c +index acfabfe07c4fa..fc5b5b2c9e819 100644 +--- a/drivers/acpi/processor_idle.c ++++ b/drivers/acpi/processor_idle.c +@@ -1134,6 +1134,9 @@ static int acpi_processor_get_lpi_info(struct acpi_processor *pr) + status = acpi_get_parent(handle, &pr_ahandle); + while (ACPI_SUCCESS(status)) { + d = acpi_fetch_acpi_dev(pr_ahandle); ++ if (!d) ++ break; ++ + handle = pr_ahandle; + + if (strcmp(acpi_device_hid(d), ACPI_PROCESSOR_CONTAINER_HID)) +diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c +index f27914aedbd5a..16dcd31d124fe 100644 +--- a/drivers/acpi/resource.c ++++ b/drivers/acpi/resource.c +@@ -432,10 +432,24 @@ static const struct dmi_system_id asus_laptop[] = { + DMI_MATCH(DMI_BOARD_NAME, "S5602ZA"), + }, + }, ++ { ++ .ident = "Asus ExpertBook B2502", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), ++ DMI_MATCH(DMI_BOARD_NAME, "B2502CBA"), ++ }, ++ }, + { } + }; + +-static const struct dmi_system_id lenovo_82ra[] = { ++static const struct dmi_system_id lenovo_laptop[] = { ++ { ++ .ident = "LENOVO IdeaPad Flex 5 14ALC7", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "82R9"), ++ }, ++ }, + { + .ident = "LENOVO IdeaPad Flex 5 16ALC7", + .matches = { +@@ -446,6 +460,17 @@ static const struct dmi_system_id lenovo_82ra[] = { + { } + }; + ++static const struct dmi_system_id schenker_gm_rg[] = { ++ { ++ .ident = "XMG CORE 15 (M22)", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"), ++ DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"), ++ }, ++ }, ++ { } ++}; ++ + struct irq_override_cmp { + const struct dmi_system_id *system; + unsigned char irq; +@@ -458,8 +483,9 @@ struct irq_override_cmp { + static const struct irq_override_cmp override_table[] = { + { medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, + { asus_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, +- { lenovo_82ra, 6, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, true }, +- { lenovo_82ra, 10, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, true }, ++ { lenovo_laptop, 6, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, true }, ++ { lenovo_laptop, 10, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, true }, ++ { schenker_gm_rg, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true }, + }; + + static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity, +diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c +index b2a6162876387..13f10fbcd7f03 100644 +--- a/drivers/acpi/video_detect.c ++++ b/drivers/acpi/video_detect.c +@@ -34,6 +34,7 @@ + #include <linux/module.h> + #include <linux/pci.h> + #include <linux/platform_data/x86/nvidia-wmi-ec-backlight.h> ++#include <linux/pnp.h> + #include <linux/types.h> + #include <linux/workqueue.h> + #include <acpi/video.h> +@@ -105,6 +106,26 @@ static bool nvidia_wmi_ec_supported(void) + } + #endif + ++static bool apple_gmux_backlight_present(void) ++{ ++ struct acpi_device *adev; ++ struct device *dev; ++ ++ adev = acpi_dev_get_first_match_dev(GMUX_ACPI_HID, NULL, -1); ++ if (!adev) ++ return false; ++ ++ dev = acpi_get_first_physical_node(adev); ++ if (!dev) ++ return false; ++ ++ /* ++ * drivers/platform/x86/apple-gmux.c only supports old style ++ * Apple GMUX with an IO-resource. ++ */ ++ return pnp_get_resource(to_pnp_dev(dev), IORESOURCE_IO, 0) != NULL; ++} ++ + /* Force to use vendor driver when the ACPI device is known to be + * buggy */ + static int video_detect_force_vendor(const struct dmi_system_id *d) +@@ -132,6 +153,10 @@ static int video_detect_force_none(const struct dmi_system_id *d) + } + + static const struct dmi_system_id video_detect_dmi_table[] = { ++ /* ++ * Models which should use the vendor backlight interface, ++ * because of broken ACPI video backlight control. ++ */ + { + /* https://bugzilla.redhat.com/show_bug.cgi?id=1128309 */ + .callback = video_detect_force_vendor, +@@ -197,14 +222,6 @@ static const struct dmi_system_id video_detect_dmi_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "1015CX"), + }, + }, +- { +- .callback = video_detect_force_vendor, +- /* GIGABYTE GB-BXBT-2807 */ +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), +- DMI_MATCH(DMI_PRODUCT_NAME, "GB-BXBT-2807"), +- }, +- }, + { + .callback = video_detect_force_vendor, + /* Samsung N150/N210/N220 */ +@@ -234,18 +251,23 @@ static const struct dmi_system_id video_detect_dmi_table[] = { + }, + { + .callback = video_detect_force_vendor, +- /* Sony VPCEH3U1E */ ++ /* Xiaomi Mi Pad 2 */ + .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), +- DMI_MATCH(DMI_PRODUCT_NAME, "VPCEH3U1E"), ++ DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"), + }, + }, ++ ++ /* ++ * Models which should use the vendor backlight interface, ++ * because of broken native backlight control. ++ */ + { + .callback = video_detect_force_vendor, +- /* Xiaomi Mi Pad 2 */ ++ /* Sony Vaio PCG-FRV35 */ + .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"), +- DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"), ++ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "PCG-FRV35"), + }, + }, + +@@ -609,6 +631,23 @@ static const struct dmi_system_id video_detect_dmi_table[] = { + DMI_MATCH(DMI_BOARD_NAME, "N250P"), + }, + }, ++ { ++ /* https://bugzilla.kernel.org/show_bug.cgi?id=202401 */ ++ .callback = video_detect_force_native, ++ /* Sony Vaio VPCEH3U1E */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "VPCEH3U1E"), ++ }, ++ }, ++ { ++ .callback = video_detect_force_native, ++ /* Sony Vaio VPCY11S1E */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "VPCY11S1E"), ++ }, ++ }, + + /* + * These Toshibas have a broken acpi-video interface for brightness +@@ -671,6 +710,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 9020M"), + }, + }, ++ { ++ .callback = video_detect_force_none, ++ /* GIGABYTE GB-BXBT-2807 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "GB-BXBT-2807"), ++ }, ++ }, + { + .callback = video_detect_force_none, + /* MSI MS-7721 */ +@@ -729,7 +776,7 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native) + if (nvidia_wmi_ec_present) + return acpi_backlight_nvidia_wmi_ec; + +- if (apple_gmux_present()) ++ if (apple_gmux_backlight_present()) + return acpi_backlight_apple_gmux; + + /* Chromebooks should always prefer native backlight control. */ +diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c +index 5350c73564b60..c7afce465a071 100644 +--- a/drivers/acpi/x86/s2idle.c ++++ b/drivers/acpi/x86/s2idle.c +@@ -28,10 +28,6 @@ static bool sleep_no_lps0 __read_mostly; + module_param(sleep_no_lps0, bool, 0644); + MODULE_PARM_DESC(sleep_no_lps0, "Do not use the special LPS0 device interface"); + +-static bool prefer_microsoft_dsm_guid __read_mostly; +-module_param(prefer_microsoft_dsm_guid, bool, 0644); +-MODULE_PARM_DESC(prefer_microsoft_dsm_guid, "Prefer using Microsoft GUID in LPS0 device _DSM evaluation"); +- + static const struct acpi_device_id lps0_device_ids[] = { + {"PNP0D80", }, + {"", }, +@@ -369,27 +365,15 @@ out: + } + + struct amd_lps0_hid_device_data { +- const unsigned int rev_id; + const bool check_off_by_one; +- const bool prefer_amd_guid; + }; + + static const struct amd_lps0_hid_device_data amd_picasso = { +- .rev_id = 0, + .check_off_by_one = true, +- .prefer_amd_guid = false, + }; + + static const struct amd_lps0_hid_device_data amd_cezanne = { +- .rev_id = 0, +- .check_off_by_one = false, +- .prefer_amd_guid = false, +-}; +- +-static const struct amd_lps0_hid_device_data amd_rembrandt = { +- .rev_id = 2, + .check_off_by_one = false, +- .prefer_amd_guid = true, + }; + + static const struct acpi_device_id amd_hid_ids[] = { +@@ -397,69 +381,27 @@ static const struct acpi_device_id amd_hid_ids[] = { + {"AMD0005", (kernel_ulong_t)&amd_picasso, }, + {"AMDI0005", (kernel_ulong_t)&amd_picasso, }, + {"AMDI0006", (kernel_ulong_t)&amd_cezanne, }, +- {"AMDI0007", (kernel_ulong_t)&amd_rembrandt, }, + {} + }; + +-static int lps0_prefer_microsoft(const struct dmi_system_id *id) ++static int lps0_prefer_amd(const struct dmi_system_id *id) + { +- pr_debug("Preferring Microsoft GUID.\n"); +- prefer_microsoft_dsm_guid = true; ++ pr_debug("Using AMD GUID w/ _REV 2.\n"); ++ rev_id = 2; + return 0; + } +- + static const struct dmi_system_id s2idle_dmi_table[] __initconst = { + { + /* +- * ASUS TUF Gaming A17 FA707RE +- * https://bugzilla.kernel.org/show_bug.cgi?id=216101 +- */ +- .callback = lps0_prefer_microsoft, +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +- DMI_MATCH(DMI_PRODUCT_NAME, "ASUS TUF Gaming A17"), +- }, +- }, +- { +- /* ASUS ROG Zephyrus G14 (2022) */ +- .callback = lps0_prefer_microsoft, +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +- DMI_MATCH(DMI_PRODUCT_NAME, "ROG Zephyrus G14 GA402"), +- }, +- }, +- { +- /* +- * Lenovo Yoga Slim 7 Pro X 14ARH7 +- * https://bugzilla.kernel.org/show_bug.cgi?id=216473 : 82V2 +- * https://bugzilla.kernel.org/show_bug.cgi?id=216438 : 82TL +- */ +- .callback = lps0_prefer_microsoft, +- .matches = { +- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), +- DMI_MATCH(DMI_PRODUCT_NAME, "82"), +- }, +- }, +- { +- /* +- * ASUSTeK COMPUTER INC. ROG Flow X13 GV301RE_GV301RE +- * https://gitlab.freedesktop.org/drm/amd/-/issues/2148 ++ * AMD Rembrandt based HP EliteBook 835/845/865 G9 ++ * Contains specialized AML in AMD/_REV 2 path to avoid ++ * triggering a bug in Qualcomm WLAN firmware. This may be ++ * removed in the future if that firmware is fixed. + */ +- .callback = lps0_prefer_microsoft, ++ .callback = lps0_prefer_amd, + .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +- DMI_MATCH(DMI_PRODUCT_NAME, "ROG Flow X13 GV301"), +- }, +- }, +- { +- /* +- * ASUSTeK COMPUTER INC. ROG Flow X16 GV601RW_GV601RW +- * https://gitlab.freedesktop.org/drm/amd/-/issues/2148 +- */ +- .callback = lps0_prefer_microsoft, +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +- DMI_MATCH(DMI_PRODUCT_NAME, "ROG Flow X16 GV601"), ++ DMI_MATCH(DMI_BOARD_VENDOR, "HP"), ++ DMI_MATCH(DMI_BOARD_NAME, "8990"), + }, + }, + {} +@@ -484,16 +426,14 @@ static int lps0_device_attach(struct acpi_device *adev, + if (dev_id->id[0]) + data = (const struct amd_lps0_hid_device_data *) dev_id->driver_data; + else +- data = &amd_rembrandt; +- rev_id = data->rev_id; ++ data = &amd_cezanne; + lps0_dsm_func_mask = validate_dsm(adev->handle, + ACPI_LPS0_DSM_UUID_AMD, rev_id, &lps0_dsm_guid); + if (lps0_dsm_func_mask > 0x3 && data->check_off_by_one) { + lps0_dsm_func_mask = (lps0_dsm_func_mask << 1) | 0x1; + acpi_handle_debug(adev->handle, "_DSM UUID %s: Adjusted function mask: 0x%x\n", + ACPI_LPS0_DSM_UUID_AMD, lps0_dsm_func_mask); +- } else if (lps0_dsm_func_mask_microsoft > 0 && data->prefer_amd_guid && +- !prefer_microsoft_dsm_guid) { ++ } else if (lps0_dsm_func_mask_microsoft > 0 && rev_id) { + lps0_dsm_func_mask_microsoft = -EINVAL; + acpi_handle_debug(adev->handle, "_DSM Using AMD method\n"); + } +@@ -501,8 +441,7 @@ static int lps0_device_attach(struct acpi_device *adev, + rev_id = 1; + lps0_dsm_func_mask = validate_dsm(adev->handle, + ACPI_LPS0_DSM_UUID, rev_id, &lps0_dsm_guid); +- if (!prefer_microsoft_dsm_guid) +- lps0_dsm_func_mask_microsoft = -EINVAL; ++ lps0_dsm_func_mask_microsoft = -EINVAL; + } + + if (lps0_dsm_func_mask < 0 && lps0_dsm_func_mask_microsoft < 0) +diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c +index d7d3f1669d4c0..4e816bb402f68 100644 +--- a/drivers/acpi/x86/utils.c ++++ b/drivers/acpi/x86/utils.c +@@ -308,7 +308,7 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { + ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), + }, + { +- /* Lenovo Yoga Tablet 1050F/L */ ++ /* Lenovo Yoga Tablet 2 1050F/L */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."), + DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"), +@@ -319,6 +319,27 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { + .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | + ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), + }, ++ { ++ /* Lenovo Yoga Tab 3 Pro X90F */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"), ++ }, ++ .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | ++ ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), ++ }, ++ { ++ /* Medion Lifetab S10346 */ ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), ++ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), ++ /* Way too generic, also match on BIOS data */ ++ DMI_MATCH(DMI_BIOS_DATE, "10/22/2015"), ++ }, ++ .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | ++ ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), ++ }, + { + /* Nextbook Ares 8 */ + .matches = { +@@ -348,6 +369,7 @@ static const struct acpi_device_id i2c_acpi_known_good_ids[] = { + { "10EC5640", 0 }, /* RealTek ALC5640 audio codec */ + { "INT33F4", 0 }, /* X-Powers AXP288 PMIC */ + { "INT33FD", 0 }, /* Intel Crystal Cove PMIC */ ++ { "INT34D3", 0 }, /* Intel Whiskey Cove PMIC */ + { "NPCE69A", 0 }, /* Asus Transformer keyboard dock */ + {} + }; +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index 639de2d75d636..53ab2306da009 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -84,6 +84,7 @@ enum board_ids { + static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); + static void ahci_remove_one(struct pci_dev *dev); + static void ahci_shutdown_one(struct pci_dev *dev); ++static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hpriv); + static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline); + static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, +@@ -677,6 +678,25 @@ static void ahci_pci_save_initial_config(struct pci_dev *pdev, + ahci_save_initial_config(&pdev->dev, hpriv); + } + ++static int ahci_pci_reset_controller(struct ata_host *host) ++{ ++ struct pci_dev *pdev = to_pci_dev(host->dev); ++ struct ahci_host_priv *hpriv = host->private_data; ++ int rc; ++ ++ rc = ahci_reset_controller(host); ++ if (rc) ++ return rc; ++ ++ /* ++ * If platform firmware failed to enable ports, try to enable ++ * them here. ++ */ ++ ahci_intel_pcs_quirk(pdev, hpriv); ++ ++ return 0; ++} ++ + static void ahci_pci_init_controller(struct ata_host *host) + { + struct ahci_host_priv *hpriv = host->private_data; +@@ -871,7 +891,7 @@ static int ahci_pci_device_runtime_resume(struct device *dev) + struct ata_host *host = pci_get_drvdata(pdev); + int rc; + +- rc = ahci_reset_controller(host); ++ rc = ahci_pci_reset_controller(host); + if (rc) + return rc; + ahci_pci_init_controller(host); +@@ -907,7 +927,7 @@ static int ahci_pci_device_resume(struct device *dev) + ahci_mcp89_apple_enable(pdev); + + if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { +- rc = ahci_reset_controller(host); ++ rc = ahci_pci_reset_controller(host); + if (rc) + return rc; + +@@ -1785,12 +1805,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + /* save initial config */ + ahci_pci_save_initial_config(pdev, hpriv); + +- /* +- * If platform firmware failed to enable ports, try to enable +- * them here. +- */ +- ahci_intel_pcs_quirk(pdev, hpriv); +- + /* prepare host */ + if (hpriv->cap & HOST_CAP_NCQ) { + pi.flags |= ATA_FLAG_NCQ; +@@ -1900,7 +1914,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + if (rc) + return rc; + +- rc = ahci_reset_controller(host); ++ rc = ahci_pci_reset_controller(host); + if (rc) + return rc; + +diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c +index b6806d41a8c50..fd4dccc253896 100644 +--- a/drivers/ata/libata-sata.c ++++ b/drivers/ata/libata-sata.c +@@ -1392,7 +1392,8 @@ static int ata_eh_read_log_10h(struct ata_device *dev, + tf->hob_lbah = buf[10]; + tf->nsect = buf[12]; + tf->hob_nsect = buf[13]; +- if (dev->class == ATA_DEV_ZAC && ata_id_has_ncq_autosense(dev->id)) ++ if (dev->class == ATA_DEV_ZAC && ata_id_has_ncq_autosense(dev->id) && ++ (tf->status & ATA_SENSE)) + tf->auxiliary = buf[14] << 16 | buf[15] << 8 | buf[16]; + + return 0; +@@ -1456,8 +1457,12 @@ void ata_eh_analyze_ncq_error(struct ata_link *link) + memcpy(&qc->result_tf, &tf, sizeof(tf)); + qc->result_tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_LBA | ATA_TFLAG_LBA48; + qc->err_mask |= AC_ERR_DEV | AC_ERR_NCQ; +- if (dev->class == ATA_DEV_ZAC && +- ((qc->result_tf.status & ATA_SENSE) || qc->result_tf.auxiliary)) { ++ ++ /* ++ * If the device supports NCQ autosense, ata_eh_read_log_10h() will have ++ * stored the sense data in qc->result_tf.auxiliary. ++ */ ++ if (qc->result_tf.auxiliary) { + char sense_key, asc, ascq; + + sense_key = (qc->result_tf.auxiliary >> 16) & 0xff; +diff --git a/drivers/base/class.c b/drivers/base/class.c +index 64f7b9a0970f7..8ceafb7d0203b 100644 +--- a/drivers/base/class.c ++++ b/drivers/base/class.c +@@ -192,6 +192,11 @@ int __class_register(struct class *cls, struct lock_class_key *key) + } + error = class_add_groups(class_get(cls), cls->class_groups); + class_put(cls); ++ if (error) { ++ kobject_del(&cp->subsys.kobj); ++ kfree_const(cp->subsys.kobj.name); ++ kfree(cp); ++ } + return error; + } + EXPORT_SYMBOL_GPL(__class_register); +diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c +index b52049098d4ee..14088b5adb556 100644 +--- a/drivers/base/power/runtime.c ++++ b/drivers/base/power/runtime.c +@@ -484,7 +484,17 @@ static int rpm_idle(struct device *dev, int rpmflags) + + dev->power.idle_notification = true; + +- retval = __rpm_callback(callback, dev); ++ if (dev->power.irq_safe) ++ spin_unlock(&dev->power.lock); ++ else ++ spin_unlock_irq(&dev->power.lock); ++ ++ retval = callback(dev); ++ ++ if (dev->power.irq_safe) ++ spin_lock(&dev->power.lock); ++ else ++ spin_lock_irq(&dev->power.lock); + + dev->power.idle_notification = false; + wake_up_all(&dev->power.wait_queue); +diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c +index 4ef9488d05cde..3de89795f5843 100644 +--- a/drivers/base/regmap/regmap-irq.c ++++ b/drivers/base/regmap/regmap-irq.c +@@ -722,6 +722,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, + int i; + int ret = -ENOMEM; + int num_type_reg; ++ int num_regs; + u32 reg; + + if (chip->num_regs <= 0) +@@ -796,14 +797,20 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, + goto err_alloc; + } + +- num_type_reg = chip->type_in_mask ? chip->num_regs : chip->num_type_reg; +- if (num_type_reg) { +- d->type_buf_def = kcalloc(num_type_reg, ++ /* ++ * Use num_config_regs if defined, otherwise fall back to num_type_reg ++ * to maintain backward compatibility. ++ */ ++ num_type_reg = chip->num_config_regs ? chip->num_config_regs ++ : chip->num_type_reg; ++ num_regs = chip->type_in_mask ? chip->num_regs : num_type_reg; ++ if (num_regs) { ++ d->type_buf_def = kcalloc(num_regs, + sizeof(*d->type_buf_def), GFP_KERNEL); + if (!d->type_buf_def) + goto err_alloc; + +- d->type_buf = kcalloc(num_type_reg, sizeof(*d->type_buf), ++ d->type_buf = kcalloc(num_regs, sizeof(*d->type_buf), + GFP_KERNEL); + if (!d->type_buf) + goto err_alloc; +diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c +index 8532b839a3435..6772402326842 100644 +--- a/drivers/block/drbd/drbd_main.c ++++ b/drivers/block/drbd/drbd_main.c +@@ -2217,7 +2217,8 @@ void drbd_destroy_device(struct kref *kref) + kref_put(&peer_device->connection->kref, drbd_destroy_connection); + kfree(peer_device); + } +- memset(device, 0xfd, sizeof(*device)); ++ if (device->submit.wq) ++ destroy_workqueue(device->submit.wq); + kfree(device); + kref_put(&resource->kref, drbd_destroy_resource); + } +@@ -2309,7 +2310,6 @@ void drbd_destroy_resource(struct kref *kref) + idr_destroy(&resource->devices); + free_cpumask_var(resource->cpu_mask); + kfree(resource->name); +- memset(resource, 0xf2, sizeof(*resource)); + kfree(resource); + } + +@@ -2650,7 +2650,6 @@ void drbd_destroy_connection(struct kref *kref) + drbd_free_socket(&connection->data); + kfree(connection->int_dig_in); + kfree(connection->int_dig_vv); +- memset(connection, 0xfc, sizeof(*connection)); + kfree(connection); + kref_put(&resource->kref, drbd_destroy_resource); + } +@@ -2774,7 +2773,7 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig + + err = add_disk(disk); + if (err) +- goto out_idr_remove_from_resource; ++ goto out_destroy_workqueue; + + /* inherit the connection state */ + device->state.conn = first_connection(resource)->cstate; +@@ -2788,6 +2787,8 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig + drbd_debugfs_device_add(device); + return NO_ERROR; + ++out_destroy_workqueue: ++ destroy_workqueue(device->submit.wq); + out_idr_remove_from_resource: + for_each_connection_safe(connection, n, resource) { + peer_device = idr_remove(&connection->peer_devices, vnr); +diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c +index 864c98e748757..249eba7d21c28 100644 +--- a/drivers/block/drbd/drbd_nl.c ++++ b/drivers/block/drbd/drbd_nl.c +@@ -1210,6 +1210,7 @@ static void decide_on_discard_support(struct drbd_device *device, + struct drbd_connection *connection = + first_peer_device(device)->connection; + struct request_queue *q = device->rq_queue; ++ unsigned int max_discard_sectors; + + if (bdev && !bdev_max_discard_sectors(bdev->backing_bdev)) + goto not_supported; +@@ -1230,15 +1231,14 @@ static void decide_on_discard_support(struct drbd_device *device, + * topology on all peers. + */ + blk_queue_discard_granularity(q, 512); +- q->limits.max_discard_sectors = drbd_max_discard_sectors(connection); +- q->limits.max_write_zeroes_sectors = +- drbd_max_discard_sectors(connection); ++ max_discard_sectors = drbd_max_discard_sectors(connection); ++ blk_queue_max_discard_sectors(q, max_discard_sectors); ++ blk_queue_max_write_zeroes_sectors(q, max_discard_sectors); + return; + + not_supported: + blk_queue_discard_granularity(q, 0); +- q->limits.max_discard_sectors = 0; +- q->limits.max_write_zeroes_sectors = 0; ++ blk_queue_max_discard_sectors(q, 0); + } + + static void fixup_write_zeroes(struct drbd_device *device, struct request_queue *q) +diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c +index ccad3d7b3ddd9..487840e3564df 100644 +--- a/drivers/block/floppy.c ++++ b/drivers/block/floppy.c +@@ -4593,8 +4593,10 @@ static int __init do_floppy_init(void) + goto out_put_disk; + + err = floppy_alloc_disk(drive, 0); +- if (err) ++ if (err) { ++ blk_mq_free_tag_set(&tag_sets[drive]); + goto out_put_disk; ++ } + + timer_setup(&motor_off_timer[drive], motor_off_callback, 0); + } +diff --git a/drivers/block/loop.c b/drivers/block/loop.c +index ad92192c7d617..d12d3d171ec4c 100644 +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -1773,7 +1773,16 @@ static const struct block_device_operations lo_fops = { + /* + * And now the modules code and kernel interface. + */ +-static int max_loop; ++ ++/* ++ * If max_loop is specified, create that many devices upfront. ++ * This also becomes a hard limit. If max_loop is not specified, ++ * create CONFIG_BLK_DEV_LOOP_MIN_COUNT loop devices at module ++ * init time. Loop devices can be requested on-demand with the ++ * /dev/loop-control interface, or be instantiated by accessing ++ * a 'dead' device node. ++ */ ++static int max_loop = CONFIG_BLK_DEV_LOOP_MIN_COUNT; + module_param(max_loop, int, 0444); + MODULE_PARM_DESC(max_loop, "Maximum number of loop devices"); + module_param(max_part, int, 0444); +@@ -2181,7 +2190,7 @@ MODULE_ALIAS("devname:loop-control"); + + static int __init loop_init(void) + { +- int i, nr; ++ int i; + int err; + + part_shift = 0; +@@ -2209,19 +2218,6 @@ static int __init loop_init(void) + goto err_out; + } + +- /* +- * If max_loop is specified, create that many devices upfront. +- * This also becomes a hard limit. If max_loop is not specified, +- * create CONFIG_BLK_DEV_LOOP_MIN_COUNT loop devices at module +- * init time. Loop devices can be requested on-demand with the +- * /dev/loop-control interface, or be instantiated by accessing +- * a 'dead' device node. +- */ +- if (max_loop) +- nr = max_loop; +- else +- nr = CONFIG_BLK_DEV_LOOP_MIN_COUNT; +- + err = misc_register(&loop_misc); + if (err < 0) + goto err_out; +@@ -2233,7 +2229,7 @@ static int __init loop_init(void) + } + + /* pre-create number of devices given by config or max_loop */ +- for (i = 0; i < nr; i++) ++ for (i = 0; i < max_loop; i++) + loop_add(i); + + printk(KERN_INFO "loop: module loaded\n"); +diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c +index a657e9a3e96a5..f6b4b7a1be4cc 100644 +--- a/drivers/bluetooth/btintel.c ++++ b/drivers/bluetooth/btintel.c +@@ -2524,7 +2524,7 @@ static int btintel_setup_combined(struct hci_dev *hdev) + */ + err = btintel_read_version(hdev, &ver); + if (err) +- return err; ++ break; + + /* Apply the device specific HCI quirks + * +@@ -2566,7 +2566,8 @@ static int btintel_setup_combined(struct hci_dev *hdev) + default: + bt_dev_err(hdev, "Unsupported Intel hw variant (%u)", + INTEL_HW_VARIANT(ver_tlv.cnvi_bt)); +- return -EINVAL; ++ err = -EINVAL; ++ break; + } + + exit_error: +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index f05018988a177..6beafd62d7226 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -802,13 +802,13 @@ static inline void btusb_free_frags(struct btusb_data *data) + + spin_lock_irqsave(&data->rxlock, flags); + +- kfree_skb(data->evt_skb); ++ dev_kfree_skb_irq(data->evt_skb); + data->evt_skb = NULL; + +- kfree_skb(data->acl_skb); ++ dev_kfree_skb_irq(data->acl_skb); + data->acl_skb = NULL; + +- kfree_skb(data->sco_skb); ++ dev_kfree_skb_irq(data->sco_skb); + data->sco_skb = NULL; + + spin_unlock_irqrestore(&data->rxlock, flags); +diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c +index d7e0b75db8a60..2b6c0e1922cb3 100644 +--- a/drivers/bluetooth/hci_bcm.c ++++ b/drivers/bluetooth/hci_bcm.c +@@ -53,11 +53,13 @@ + * struct bcm_device_data - device specific data + * @no_early_set_baudrate: Disallow set baudrate before driver setup() + * @drive_rts_on_open: drive RTS signal on ->open() when platform requires it ++ * @no_uart_clock_set: UART clock set command for >3Mbps mode is unavailable + * @max_autobaud_speed: max baudrate supported by device in autobaud mode + */ + struct bcm_device_data { + bool no_early_set_baudrate; + bool drive_rts_on_open; ++ bool no_uart_clock_set; + u32 max_autobaud_speed; + }; + +@@ -100,6 +102,7 @@ struct bcm_device_data { + * @is_suspended: whether flow control is currently disabled + * @no_early_set_baudrate: don't set_baudrate before setup() + * @drive_rts_on_open: drive RTS signal on ->open() when platform requires it ++ * @no_uart_clock_set: UART clock set command for >3Mbps mode is unavailable + * @pcm_int_params: keep the initial PCM configuration + * @use_autobaud_mode: start Bluetooth device in autobaud mode + * @max_autobaud_speed: max baudrate supported by device in autobaud mode +@@ -140,6 +143,7 @@ struct bcm_device { + #endif + bool no_early_set_baudrate; + bool drive_rts_on_open; ++ bool no_uart_clock_set; + bool use_autobaud_mode; + u8 pcm_int_params[5]; + u32 max_autobaud_speed; +@@ -172,10 +176,11 @@ static inline void host_set_baudrate(struct hci_uart *hu, unsigned int speed) + static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed) + { + struct hci_dev *hdev = hu->hdev; ++ struct bcm_data *bcm = hu->priv; + struct sk_buff *skb; + struct bcm_update_uart_baud_rate param; + +- if (speed > 3000000) { ++ if (speed > 3000000 && !bcm->dev->no_uart_clock_set) { + struct bcm_write_uart_clock_setting clock; + + clock.type = BCM_UART_CLOCK_48MHZ; +@@ -1529,6 +1534,7 @@ static int bcm_serdev_probe(struct serdev_device *serdev) + bcmdev->max_autobaud_speed = data->max_autobaud_speed; + bcmdev->no_early_set_baudrate = data->no_early_set_baudrate; + bcmdev->drive_rts_on_open = data->drive_rts_on_open; ++ bcmdev->no_uart_clock_set = data->no_uart_clock_set; + } + + return hci_uart_register_device(&bcmdev->serdev_hu, &bcm_proto); +@@ -1550,6 +1556,10 @@ static struct bcm_device_data bcm43438_device_data = { + .drive_rts_on_open = true, + }; + ++static struct bcm_device_data cyw4373a0_device_data = { ++ .no_uart_clock_set = true, ++}; ++ + static struct bcm_device_data cyw55572_device_data = { + .max_autobaud_speed = 921600, + }; +@@ -1566,6 +1576,7 @@ static const struct of_device_id bcm_bluetooth_of_match[] = { + { .compatible = "brcm,bcm4349-bt", .data = &bcm43438_device_data }, + { .compatible = "brcm,bcm43540-bt", .data = &bcm4354_device_data }, + { .compatible = "brcm,bcm4335a0" }, ++ { .compatible = "cypress,cyw4373a0-bt", .data = &cyw4373a0_device_data }, + { .compatible = "infineon,cyw55572-bt", .data = &cyw55572_device_data }, + { }, + }; +diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c +index cf4a560958173..8055f63603f45 100644 +--- a/drivers/bluetooth/hci_bcsp.c ++++ b/drivers/bluetooth/hci_bcsp.c +@@ -378,7 +378,7 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp) + i++; + + __skb_unlink(skb, &bcsp->unack); +- kfree_skb(skb); ++ dev_kfree_skb_irq(skb); + } + + if (skb_queue_empty(&bcsp->unack)) +diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c +index c5a0409ef84fd..6455bc4fb5bb3 100644 +--- a/drivers/bluetooth/hci_h5.c ++++ b/drivers/bluetooth/hci_h5.c +@@ -313,7 +313,7 @@ static void h5_pkt_cull(struct h5 *h5) + break; + + __skb_unlink(skb, &h5->unack); +- kfree_skb(skb); ++ dev_kfree_skb_irq(skb); + } + + if (skb_queue_empty(&h5->unack)) +diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c +index 4eb420a9ed04e..5abc01a2acf72 100644 +--- a/drivers/bluetooth/hci_ll.c ++++ b/drivers/bluetooth/hci_ll.c +@@ -345,7 +345,7 @@ static int ll_enqueue(struct hci_uart *hu, struct sk_buff *skb) + default: + BT_ERR("illegal hcill state: %ld (losing packet)", + ll->hcill_state); +- kfree_skb(skb); ++ dev_kfree_skb_irq(skb); + break; + } + +diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c +index 8df11016fd51b..bae9b2a408d95 100644 +--- a/drivers/bluetooth/hci_qca.c ++++ b/drivers/bluetooth/hci_qca.c +@@ -912,7 +912,7 @@ static int qca_enqueue(struct hci_uart *hu, struct sk_buff *skb) + default: + BT_ERR("Illegal tx state: %d (losing packet)", + qca->tx_ibs_state); +- kfree_skb(skb); ++ dev_kfree_skb_irq(skb); + break; + } + +diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c +index c22d4184bb612..0555e3838bce1 100644 +--- a/drivers/char/hw_random/amd-rng.c ++++ b/drivers/char/hw_random/amd-rng.c +@@ -143,15 +143,19 @@ static int __init amd_rng_mod_init(void) + found: + err = pci_read_config_dword(pdev, 0x58, &pmbase); + if (err) +- return err; ++ goto put_dev; + + pmbase &= 0x0000FF00; +- if (pmbase == 0) +- return -EIO; ++ if (pmbase == 0) { ++ err = -EIO; ++ goto put_dev; ++ } + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; ++ if (!priv) { ++ err = -ENOMEM; ++ goto put_dev; ++ } + + if (!request_region(pmbase + PMBASE_OFFSET, PMBASE_SIZE, DRV_NAME)) { + dev_err(&pdev->dev, DRV_NAME " region 0x%x already in use!\n", +@@ -185,6 +189,8 @@ err_iomap: + release_region(pmbase + PMBASE_OFFSET, PMBASE_SIZE); + out: + kfree(priv); ++put_dev: ++ pci_dev_put(pdev); + return err; + } + +@@ -200,6 +206,8 @@ static void __exit amd_rng_mod_exit(void) + + release_region(priv->pmbase + PMBASE_OFFSET, PMBASE_SIZE); + ++ pci_dev_put(priv->pcidev); ++ + kfree(priv); + } + +diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c +index 138ce434f86b2..12fbe80918319 100644 +--- a/drivers/char/hw_random/geode-rng.c ++++ b/drivers/char/hw_random/geode-rng.c +@@ -51,6 +51,10 @@ static const struct pci_device_id pci_tbl[] = { + }; + MODULE_DEVICE_TABLE(pci, pci_tbl); + ++struct amd_geode_priv { ++ struct pci_dev *pcidev; ++ void __iomem *membase; ++}; + + static int geode_rng_data_read(struct hwrng *rng, u32 *data) + { +@@ -90,6 +94,7 @@ static int __init geode_rng_init(void) + const struct pci_device_id *ent; + void __iomem *mem; + unsigned long rng_base; ++ struct amd_geode_priv *priv; + + for_each_pci_dev(pdev) { + ent = pci_match_id(pci_tbl, pdev); +@@ -97,17 +102,26 @@ static int __init geode_rng_init(void) + goto found; + } + /* Device not found. */ +- goto out; ++ return err; + + found: ++ priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ if (!priv) { ++ err = -ENOMEM; ++ goto put_dev; ++ } ++ + rng_base = pci_resource_start(pdev, 0); + if (rng_base == 0) +- goto out; ++ goto free_priv; + err = -ENOMEM; + mem = ioremap(rng_base, 0x58); + if (!mem) +- goto out; +- geode_rng.priv = (unsigned long)mem; ++ goto free_priv; ++ ++ geode_rng.priv = (unsigned long)priv; ++ priv->membase = mem; ++ priv->pcidev = pdev; + + pr_info("AMD Geode RNG detected\n"); + err = hwrng_register(&geode_rng); +@@ -116,20 +130,26 @@ found: + err); + goto err_unmap; + } +-out: + return err; + + err_unmap: + iounmap(mem); +- goto out; ++free_priv: ++ kfree(priv); ++put_dev: ++ pci_dev_put(pdev); ++ return err; + } + + static void __exit geode_rng_exit(void) + { +- void __iomem *mem = (void __iomem *)geode_rng.priv; ++ struct amd_geode_priv *priv; + ++ priv = (struct amd_geode_priv *)geode_rng.priv; + hwrng_unregister(&geode_rng); +- iounmap(mem); ++ iounmap(priv->membase); ++ pci_dev_put(priv->pcidev); ++ kfree(priv); + } + + module_init(geode_rng_init); +diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c +index 49a1707693c9f..d5ee52be176d3 100644 +--- a/drivers/char/ipmi/ipmi_msghandler.c ++++ b/drivers/char/ipmi/ipmi_msghandler.c +@@ -3704,12 +3704,16 @@ static void deliver_smi_err_response(struct ipmi_smi *intf, + struct ipmi_smi_msg *msg, + unsigned char err) + { ++ int rv; + msg->rsp[0] = msg->data[0] | 4; + msg->rsp[1] = msg->data[1]; + msg->rsp[2] = err; + msg->rsp_size = 3; +- /* It's an error, so it will never requeue, no need to check return. */ +- handle_one_recv_msg(intf, msg); ++ ++ /* This will never requeue, but it may ask us to free the message. */ ++ rv = handle_one_recv_msg(intf, msg); ++ if (rv == 0) ++ ipmi_free_smi_msg(msg); + } + + static void cleanup_smi_msgs(struct ipmi_smi *intf) +diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c +index 19c32bf50e0e9..2dea8cd5a09ac 100644 +--- a/drivers/char/ipmi/kcs_bmc_aspeed.c ++++ b/drivers/char/ipmi/kcs_bmc_aspeed.c +@@ -406,13 +406,31 @@ static void aspeed_kcs_check_obe(struct timer_list *timer) + static void aspeed_kcs_irq_mask_update(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 state) + { + struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); ++ int rc; ++ u8 str; + + /* We don't have an OBE IRQ, emulate it */ + if (mask & KCS_BMC_EVENT_TYPE_OBE) { +- if (KCS_BMC_EVENT_TYPE_OBE & state) +- mod_timer(&priv->obe.timer, jiffies + OBE_POLL_PERIOD); +- else ++ if (KCS_BMC_EVENT_TYPE_OBE & state) { ++ /* ++ * Given we don't have an OBE IRQ, delay by polling briefly to see if we can ++ * observe such an event before returning to the caller. This is not ++ * incorrect because OBF may have already become clear before enabling the ++ * IRQ if we had one, under which circumstance no event will be propagated ++ * anyway. ++ * ++ * The onus is on the client to perform a race-free check that it hasn't ++ * missed the event. ++ */ ++ rc = read_poll_timeout_atomic(aspeed_kcs_inb, str, ++ !(str & KCS_BMC_STR_OBF), 1, 100, false, ++ &priv->kcs_bmc, priv->kcs_bmc.ioreg.str); ++ /* Time for the slow path? */ ++ if (rc == -ETIMEDOUT) ++ mod_timer(&priv->obe.timer, jiffies + OBE_POLL_PERIOD); ++ } else { + del_timer(&priv->obe.timer); ++ } + } + + if (mask & KCS_BMC_EVENT_TYPE_IBF) { +diff --git a/drivers/char/tpm/eventlog/acpi.c b/drivers/char/tpm/eventlog/acpi.c +index 1b18ce5ebab1e..0913d3eb8d518 100644 +--- a/drivers/char/tpm/eventlog/acpi.c ++++ b/drivers/char/tpm/eventlog/acpi.c +@@ -90,16 +90,21 @@ int tpm_read_log_acpi(struct tpm_chip *chip) + return -ENODEV; + + if (tbl->header.length < +- sizeof(*tbl) + sizeof(struct acpi_tpm2_phy)) ++ sizeof(*tbl) + sizeof(struct acpi_tpm2_phy)) { ++ acpi_put_table((struct acpi_table_header *)tbl); + return -ENODEV; ++ } + + tpm2_phy = (void *)tbl + sizeof(*tbl); + len = tpm2_phy->log_area_minimum_length; + + start = tpm2_phy->log_area_start_address; +- if (!start || !len) ++ if (!start || !len) { ++ acpi_put_table((struct acpi_table_header *)tbl); + return -ENODEV; ++ } + ++ acpi_put_table((struct acpi_table_header *)tbl); + format = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2; + } else { + /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */ +@@ -120,8 +125,10 @@ int tpm_read_log_acpi(struct tpm_chip *chip) + break; + } + ++ acpi_put_table((struct acpi_table_header *)buff); + format = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; + } ++ + if (!len) { + dev_warn(&chip->dev, "%s: TCPA log area empty\n", __func__); + return -EIO; +@@ -156,5 +163,4 @@ err: + kfree(log->bios_event_log); + log->bios_event_log = NULL; + return ret; +- + } +diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c +index 18606651d1aa4..16fc481d60950 100644 +--- a/drivers/char/tpm/tpm_crb.c ++++ b/drivers/char/tpm/tpm_crb.c +@@ -252,7 +252,7 @@ static int __crb_relinquish_locality(struct device *dev, + iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl); + if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, mask, value, + TPM2_TIMEOUT_C)) { +- dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed out\n"); ++ dev_warn(dev, "TPM_LOC_STATE_x.Relinquish timed out\n"); + return -ETIME; + } + +@@ -676,12 +676,16 @@ static int crb_acpi_add(struct acpi_device *device) + + /* Should the FIFO driver handle this? */ + sm = buf->start_method; +- if (sm == ACPI_TPM2_MEMORY_MAPPED) +- return -ENODEV; ++ if (sm == ACPI_TPM2_MEMORY_MAPPED) { ++ rc = -ENODEV; ++ goto out; ++ } + + priv = devm_kzalloc(dev, sizeof(struct crb_priv), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; ++ if (!priv) { ++ rc = -ENOMEM; ++ goto out; ++ } + + if (sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC) { + if (buf->header.length < (sizeof(*buf) + sizeof(*crb_smc))) { +@@ -689,7 +693,8 @@ static int crb_acpi_add(struct acpi_device *device) + FW_BUG "TPM2 ACPI table has wrong size %u for start method type %d\n", + buf->header.length, + ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC); +- return -EINVAL; ++ rc = -EINVAL; ++ goto out; + } + crb_smc = ACPI_ADD_PTR(struct tpm2_crb_smc, buf, sizeof(*buf)); + priv->smc_func_id = crb_smc->smc_func_id; +@@ -700,17 +705,23 @@ static int crb_acpi_add(struct acpi_device *device) + + rc = crb_map_io(device, priv, buf); + if (rc) +- return rc; ++ goto out; + + chip = tpmm_chip_alloc(dev, &tpm_crb); +- if (IS_ERR(chip)) +- return PTR_ERR(chip); ++ if (IS_ERR(chip)) { ++ rc = PTR_ERR(chip); ++ goto out; ++ } + + dev_set_drvdata(&chip->dev, priv); + chip->acpi_dev_handle = device->handle; + chip->flags = TPM_CHIP_FLAG_TPM2; + +- return tpm_chip_register(chip); ++ rc = tpm_chip_register(chip); ++ ++out: ++ acpi_put_table((struct acpi_table_header *)buf); ++ return rc; + } + + static int crb_acpi_remove(struct acpi_device *device) +diff --git a/drivers/char/tpm/tpm_ftpm_tee.c b/drivers/char/tpm/tpm_ftpm_tee.c +index 5c233423c56fa..deff23bb54bf1 100644 +--- a/drivers/char/tpm/tpm_ftpm_tee.c ++++ b/drivers/char/tpm/tpm_ftpm_tee.c +@@ -397,7 +397,13 @@ static int __init ftpm_mod_init(void) + if (rc) + return rc; + +- return driver_register(&ftpm_tee_driver.driver); ++ rc = driver_register(&ftpm_tee_driver.driver); ++ if (rc) { ++ platform_driver_unregister(&ftpm_tee_plat_driver); ++ return rc; ++ } ++ ++ return 0; + } + + static void __exit ftpm_mod_exit(void) +diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c +index bcff6429e0b4f..ed5dabd3c72d6 100644 +--- a/drivers/char/tpm/tpm_tis.c ++++ b/drivers/char/tpm/tpm_tis.c +@@ -125,6 +125,7 @@ static int check_acpi_tpm2(struct device *dev) + const struct acpi_device_id *aid = acpi_match_device(tpm_acpi_tbl, dev); + struct acpi_table_tpm2 *tbl; + acpi_status st; ++ int ret = 0; + + if (!aid || aid->driver_data != DEVICE_IS_TPM2) + return 0; +@@ -132,8 +133,7 @@ static int check_acpi_tpm2(struct device *dev) + /* If the ACPI TPM2 signature is matched then a global ACPI_SIG_TPM2 + * table is mandatory + */ +- st = +- acpi_get_table(ACPI_SIG_TPM2, 1, (struct acpi_table_header **)&tbl); ++ st = acpi_get_table(ACPI_SIG_TPM2, 1, (struct acpi_table_header **)&tbl); + if (ACPI_FAILURE(st) || tbl->header.length < sizeof(*tbl)) { + dev_err(dev, FW_BUG "failed to get TPM2 ACPI table\n"); + return -EINVAL; +@@ -141,9 +141,10 @@ static int check_acpi_tpm2(struct device *dev) + + /* The tpm2_crb driver handles this device */ + if (tbl->start_method != ACPI_TPM2_MEMORY_MAPPED) +- return -ENODEV; ++ ret = -ENODEV; + +- return 0; ++ acpi_put_table((struct acpi_table_header *)tbl); ++ return ret; + } + #else + static int check_acpi_tpm2(struct device *dev) +diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c +index 757623bacfd50..3f98e587b3e84 100644 +--- a/drivers/char/tpm/tpm_tis_core.c ++++ b/drivers/char/tpm/tpm_tis_core.c +@@ -682,15 +682,19 @@ static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status) + { + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + +- switch (priv->manufacturer_id) { +- case TPM_VID_WINBOND: +- return ((status == TPM_STS_VALID) || +- (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY))); +- case TPM_VID_STM: +- return (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY)); +- default: +- return (status == TPM_STS_COMMAND_READY); ++ if (!test_bit(TPM_TIS_DEFAULT_CANCELLATION, &priv->flags)) { ++ switch (priv->manufacturer_id) { ++ case TPM_VID_WINBOND: ++ return ((status == TPM_STS_VALID) || ++ (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY))); ++ case TPM_VID_STM: ++ return (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY)); ++ default: ++ break; ++ } + } ++ ++ return status == TPM_STS_COMMAND_READY; + } + + static irqreturn_t tis_int_handler(int dummy, void *dev_id) +diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h +index 66a5a13cd1df2..b68479e0de10f 100644 +--- a/drivers/char/tpm/tpm_tis_core.h ++++ b/drivers/char/tpm/tpm_tis_core.h +@@ -86,6 +86,7 @@ enum tis_defaults { + enum tpm_tis_flags { + TPM_TIS_ITPM_WORKAROUND = BIT(0), + TPM_TIS_INVALID_STATUS = BIT(1), ++ TPM_TIS_DEFAULT_CANCELLATION = BIT(2), + }; + + struct tpm_tis_data { +diff --git a/drivers/char/tpm/tpm_tis_i2c.c b/drivers/char/tpm/tpm_tis_i2c.c +index 0692510dfcab9..f3a7251c8e38f 100644 +--- a/drivers/char/tpm/tpm_tis_i2c.c ++++ b/drivers/char/tpm/tpm_tis_i2c.c +@@ -49,7 +49,7 @@ + + /* Masks with bits that must be read zero */ + #define TPM_ACCESS_READ_ZERO 0x48 +-#define TPM_INT_ENABLE_ZERO 0x7FFFFF6 ++#define TPM_INT_ENABLE_ZERO 0x7FFFFF60 + #define TPM_STS_READ_ZERO 0x23 + #define TPM_INTF_CAPABILITY_ZERO 0x0FFFF000 + #define TPM_I2C_INTERFACE_CAPABILITY_ZERO 0x80000000 +@@ -329,6 +329,7 @@ static int tpm_tis_i2c_probe(struct i2c_client *dev, + if (!phy->io_buf) + return -ENOMEM; + ++ set_bit(TPM_TIS_DEFAULT_CANCELLATION, &phy->priv.flags); + phy->i2c_client = dev; + + /* must precede all communication with the tpm */ +diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c +index d37c45b676abe..2afea905f7f3c 100644 +--- a/drivers/clk/imx/clk-imx8mn.c ++++ b/drivers/clk/imx/clk-imx8mn.c +@@ -27,10 +27,10 @@ static u32 share_count_nand; + static const char * const pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", }; + static const char * const audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", }; + static const char * const audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", }; +-static const char * const video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", }; ++static const char * const video_pll_bypass_sels[] = {"video_pll", "video_pll_ref_sel", }; + static const char * const dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", }; + static const char * const gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", }; +-static const char * const vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", }; ++static const char * const m7_alt_pll_bypass_sels[] = {"m7_alt_pll", "m7_alt_pll_ref_sel", }; + static const char * const arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", }; + static const char * const sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", }; + +@@ -40,24 +40,24 @@ static const char * const imx8mn_a53_sels[] = {"osc_24m", "arm_pll_out", "sys_pl + + static const char * const imx8mn_a53_core_sels[] = {"arm_a53_div", "arm_pll_out", }; + +-static const char * const imx8mn_m7_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_250m", "vpu_pll_out", +- "sys_pll1_800m", "audio_pll1_out", "video_pll1_out", "sys_pll3_out", }; ++static const char * const imx8mn_m7_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_250m", "m7_alt_pll_out", ++ "sys_pll1_800m", "audio_pll1_out", "video_pll_out", "sys_pll3_out", }; + + static const char * const imx8mn_gpu_core_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m", + "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out", +- "video_pll1_out", "audio_pll2_out", }; ++ "video_pll_out", "audio_pll2_out", }; + + static const char * const imx8mn_gpu_shader_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m", + "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out", +- "video_pll1_out", "audio_pll2_out", }; ++ "video_pll_out", "audio_pll2_out", }; + + static const char * const imx8mn_main_axi_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll1_800m", + "sys_pll2_250m", "sys_pll2_1000m", "audio_pll1_out", +- "video_pll1_out", "sys_pll1_100m",}; ++ "video_pll_out", "sys_pll1_100m",}; + + static const char * const imx8mn_enet_axi_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m", + "sys_pll2_250m", "sys_pll2_200m", "audio_pll1_out", +- "video_pll1_out", "sys_pll3_out", }; ++ "video_pll_out", "sys_pll3_out", }; + + static const char * const imx8mn_nand_usdhc_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m", + "sys_pll2_200m", "sys_pll1_133m", "sys_pll3_out", +@@ -77,23 +77,23 @@ static const char * const imx8mn_usb_bus_sels[] = {"osc_24m", "sys_pll2_500m", " + + static const char * const imx8mn_gpu_axi_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out", + "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out", +- "video_pll1_out", "audio_pll2_out", }; ++ "video_pll_out", "audio_pll2_out", }; + + static const char * const imx8mn_gpu_ahb_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out", + "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out", +- "video_pll1_out", "audio_pll2_out", }; ++ "video_pll_out", "audio_pll2_out", }; + + static const char * const imx8mn_noc_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll3_out", + "sys_pll2_1000m", "sys_pll2_500m", "audio_pll1_out", +- "video_pll1_out", "audio_pll2_out", }; ++ "video_pll_out", "audio_pll2_out", }; + + static const char * const imx8mn_ahb_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_800m", + "sys_pll1_400m", "sys_pll2_125m", "sys_pll3_out", +- "audio_pll1_out", "video_pll1_out", }; ++ "audio_pll1_out", "video_pll_out", }; + + static const char * const imx8mn_audio_ahb_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m", + "sys_pll2_1000m", "sys_pll2_166m", "sys_pll3_out", +- "audio_pll1_out", "video_pll1_out", }; ++ "audio_pll1_out", "video_pll_out", }; + + static const char * const imx8mn_dram_alt_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll1_100m", + "sys_pll2_500m", "sys_pll2_1000m", "sys_pll3_out", +@@ -103,49 +103,49 @@ static const char * const imx8mn_dram_apb_sels[] = {"osc_24m", "sys_pll2_200m", + "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out", + "sys_pll2_250m", "audio_pll2_out", }; + +-static const char * const imx8mn_disp_pixel_sels[] = {"osc_24m", "video_pll1_out", "audio_pll2_out", ++static const char * const imx8mn_disp_pixel_sels[] = {"osc_24m", "video_pll_out", "audio_pll2_out", + "audio_pll1_out", "sys_pll1_800m", "sys_pll2_1000m", + "sys_pll3_out", "clk_ext4", }; + + static const char * const imx8mn_sai2_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", +- "video_pll1_out", "sys_pll1_133m", "osc_hdmi", +- "clk_ext3", "clk_ext4", }; ++ "video_pll_out", "sys_pll1_133m", "dummy", ++ "clk_ext2", "clk_ext3", }; + + static const char * const imx8mn_sai3_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", +- "video_pll1_out", "sys_pll1_133m", "osc_hdmi", ++ "video_pll_out", "sys_pll1_133m", "dummy", + "clk_ext3", "clk_ext4", }; + + static const char * const imx8mn_sai5_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", +- "video_pll1_out", "sys_pll1_133m", "osc_hdmi", ++ "video_pll_out", "sys_pll1_133m", "dummy", + "clk_ext2", "clk_ext3", }; + + static const char * const imx8mn_sai6_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", +- "video_pll1_out", "sys_pll1_133m", "osc_hdmi", ++ "video_pll_out", "sys_pll1_133m", "dummy", + "clk_ext3", "clk_ext4", }; + + static const char * const imx8mn_sai7_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", +- "video_pll1_out", "sys_pll1_133m", "osc_hdmi", ++ "video_pll_out", "sys_pll1_133m", "dummy", + "clk_ext3", "clk_ext4", }; + + static const char * const imx8mn_spdif1_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", +- "video_pll1_out", "sys_pll1_133m", "osc_hdmi", ++ "video_pll_out", "sys_pll1_133m", "dummy", + "clk_ext2", "clk_ext3", }; + + static const char * const imx8mn_enet_ref_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_50m", + "sys_pll2_100m", "sys_pll1_160m", "audio_pll1_out", +- "video_pll1_out", "clk_ext4", }; ++ "video_pll_out", "clk_ext4", }; + + static const char * const imx8mn_enet_timer_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_out", + "clk_ext1", "clk_ext2", "clk_ext3", +- "clk_ext4", "video_pll1_out", }; ++ "clk_ext4", "video_pll_out", }; + + static const char * const imx8mn_enet_phy_sels[] = {"osc_24m", "sys_pll2_50m", "sys_pll2_125m", +- "sys_pll2_200m", "sys_pll2_500m", "video_pll1_out", +- "audio_pll2_out", }; ++ "sys_pll2_200m", "sys_pll2_500m", "audio_pll1_out", ++ "video_pll_out", "audio_pll2_out", }; + + static const char * const imx8mn_nand_sels[] = {"osc_24m", "sys_pll2_500m", "audio_pll1_out", + "sys_pll1_400m", "audio_pll2_out", "sys_pll3_out", +- "sys_pll2_250m", "video_pll1_out", }; ++ "sys_pll2_250m", "video_pll_out", }; + + static const char * const imx8mn_qspi_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll2_333m", + "sys_pll2_500m", "audio_pll2_out", "sys_pll1_266m", +@@ -160,19 +160,19 @@ static const char * const imx8mn_usdhc2_sels[] = {"osc_24m", "sys_pll1_400m", "s + "audio_pll2_out", "sys_pll1_100m", }; + + static const char * const imx8mn_i2c1_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", +- "sys_pll3_out", "audio_pll1_out", "video_pll1_out", ++ "sys_pll3_out", "audio_pll1_out", "video_pll_out", + "audio_pll2_out", "sys_pll1_133m", }; + + static const char * const imx8mn_i2c2_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", +- "sys_pll3_out", "audio_pll1_out", "video_pll1_out", ++ "sys_pll3_out", "audio_pll1_out", "video_pll_out", + "audio_pll2_out", "sys_pll1_133m", }; + + static const char * const imx8mn_i2c3_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", +- "sys_pll3_out", "audio_pll1_out", "video_pll1_out", ++ "sys_pll3_out", "audio_pll1_out", "video_pll_out", + "audio_pll2_out", "sys_pll1_133m", }; + + static const char * const imx8mn_i2c4_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", +- "sys_pll3_out", "audio_pll1_out", "video_pll1_out", ++ "sys_pll3_out", "audio_pll1_out", "video_pll_out", + "audio_pll2_out", "sys_pll1_133m", }; + + static const char * const imx8mn_uart1_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m", +@@ -213,63 +213,63 @@ static const char * const imx8mn_ecspi2_sels[] = {"osc_24m", "sys_pll2_200m", "s + + static const char * const imx8mn_pwm1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", + "sys_pll1_40m", "sys_pll3_out", "clk_ext1", +- "sys_pll1_80m", "video_pll1_out", }; ++ "sys_pll1_80m", "video_pll_out", }; + + static const char * const imx8mn_pwm2_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", + "sys_pll1_40m", "sys_pll3_out", "clk_ext1", +- "sys_pll1_80m", "video_pll1_out", }; ++ "sys_pll1_80m", "video_pll_out", }; + + static const char * const imx8mn_pwm3_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", + "sys_pll1_40m", "sys_pll3_out", "clk_ext2", +- "sys_pll1_80m", "video_pll1_out", }; ++ "sys_pll1_80m", "video_pll_out", }; + + static const char * const imx8mn_pwm4_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", + "sys_pll1_40m", "sys_pll3_out", "clk_ext2", +- "sys_pll1_80m", "video_pll1_out", }; ++ "sys_pll1_80m", "video_pll_out", }; + + static const char * const imx8mn_gpt1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m", +- "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m", ++ "sys_pll1_40m", "video_pll_out", "sys_pll1_80m", + "audio_pll1_out", "clk_ext1", }; + + static const char * const imx8mn_gpt2_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m", +- "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m", ++ "sys_pll1_40m", "video_pll_out", "sys_pll1_80m", + "audio_pll1_out", "clk_ext1", }; + + static const char * const imx8mn_gpt3_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m", +- "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m", ++ "sys_pll1_40m", "video_pll_out", "sys_pll1_80m", + "audio_pll1_out", "clk_ext1", }; + + static const char * const imx8mn_gpt4_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m", +- "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m", ++ "sys_pll1_40m", "video_pll_out", "sys_pll1_80m", + "audio_pll1_out", "clk_ext1", }; + + static const char * const imx8mn_gpt5_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m", +- "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m", ++ "sys_pll1_40m", "video_pll_out", "sys_pll1_80m", + "audio_pll1_out", "clk_ext1", }; + + static const char * const imx8mn_gpt6_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m", +- "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m", ++ "sys_pll1_40m", "video_pll_out", "sys_pll1_80m", + "audio_pll1_out", "clk_ext1", }; + + static const char * const imx8mn_wdog_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_160m", +- "vpu_pll_out", "sys_pll2_125m", "sys_pll3_out", ++ "m7_alt_pll_out", "sys_pll2_125m", "sys_pll3_out", + "sys_pll1_80m", "sys_pll2_166m", }; + +-static const char * const imx8mn_wrclk_sels[] = {"osc_24m", "sys_pll1_40m", "vpu_pll_out", ++static const char * const imx8mn_wrclk_sels[] = {"osc_24m", "sys_pll1_40m", "m7_alt_pll_out", + "sys_pll3_out", "sys_pll2_200m", "sys_pll1_266m", + "sys_pll2_500m", "sys_pll1_100m", }; + + static const char * const imx8mn_dsi_core_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m", + "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out", +- "audio_pll2_out", "video_pll1_out", }; ++ "audio_pll2_out", "video_pll_out", }; + + static const char * const imx8mn_dsi_phy_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_100m", + "sys_pll1_800m", "sys_pll2_1000m", "clk_ext2", +- "audio_pll2_out", "video_pll1_out", }; ++ "audio_pll2_out", "video_pll_out", }; + + static const char * const imx8mn_dsi_dbi_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_100m", + "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out", +- "audio_pll2_out", "video_pll1_out", }; ++ "audio_pll2_out", "video_pll_out", }; + + static const char * const imx8mn_usdhc3_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m", + "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m", +@@ -277,15 +277,15 @@ static const char * const imx8mn_usdhc3_sels[] = {"osc_24m", "sys_pll1_400m", "s + + static const char * const imx8mn_camera_pixel_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m", + "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out", +- "audio_pll2_out", "video_pll1_out", }; ++ "audio_pll2_out", "video_pll_out", }; + + static const char * const imx8mn_csi1_phy_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m", + "sys_pll1_800m", "sys_pll2_1000m", "clk_ext2", +- "audio_pll2_out", "video_pll1_out", }; ++ "audio_pll2_out", "video_pll_out", }; + + static const char * const imx8mn_csi2_phy_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m", + "sys_pll1_800m", "sys_pll2_1000m", "clk_ext2", +- "audio_pll2_out", "video_pll1_out", }; ++ "audio_pll2_out", "video_pll_out", }; + + static const char * const imx8mn_csi2_esc_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_80m", + "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out", +@@ -306,9 +306,9 @@ static const char * const imx8mn_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "du + "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", }; ++ "video_pll_out", "osc_32k", }; + +-static const char * const clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll1_out", ++static const char * const clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll_out", + "dummy", "dummy", "gpu_pll_out", "dummy", + "arm_pll_out", "sys_pll1", "sys_pll2", "sys_pll3", + "dummy", "dummy", "osc_24m", "dummy", "osc_32k"}; +@@ -349,19 +349,19 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) + + hws[IMX8MN_AUDIO_PLL1_REF_SEL] = imx_clk_hw_mux("audio_pll1_ref_sel", base + 0x0, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + hws[IMX8MN_AUDIO_PLL2_REF_SEL] = imx_clk_hw_mux("audio_pll2_ref_sel", base + 0x14, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); +- hws[IMX8MN_VIDEO_PLL1_REF_SEL] = imx_clk_hw_mux("video_pll1_ref_sel", base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); ++ hws[IMX8MN_VIDEO_PLL_REF_SEL] = imx_clk_hw_mux("video_pll_ref_sel", base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + hws[IMX8MN_DRAM_PLL_REF_SEL] = imx_clk_hw_mux("dram_pll_ref_sel", base + 0x50, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + hws[IMX8MN_GPU_PLL_REF_SEL] = imx_clk_hw_mux("gpu_pll_ref_sel", base + 0x64, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); +- hws[IMX8MN_VPU_PLL_REF_SEL] = imx_clk_hw_mux("vpu_pll_ref_sel", base + 0x74, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); ++ hws[IMX8MN_M7_ALT_PLL_REF_SEL] = imx_clk_hw_mux("m7_alt_pll_ref_sel", base + 0x74, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + hws[IMX8MN_ARM_PLL_REF_SEL] = imx_clk_hw_mux("arm_pll_ref_sel", base + 0x84, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + hws[IMX8MN_SYS_PLL3_REF_SEL] = imx_clk_hw_mux("sys_pll3_ref_sel", base + 0x114, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + + hws[IMX8MN_AUDIO_PLL1] = imx_clk_hw_pll14xx("audio_pll1", "audio_pll1_ref_sel", base, &imx_1443x_pll); + hws[IMX8MN_AUDIO_PLL2] = imx_clk_hw_pll14xx("audio_pll2", "audio_pll2_ref_sel", base + 0x14, &imx_1443x_pll); +- hws[IMX8MN_VIDEO_PLL1] = imx_clk_hw_pll14xx("video_pll1", "video_pll1_ref_sel", base + 0x28, &imx_1443x_pll); ++ hws[IMX8MN_VIDEO_PLL] = imx_clk_hw_pll14xx("video_pll", "video_pll_ref_sel", base + 0x28, &imx_1443x_pll); + hws[IMX8MN_DRAM_PLL] = imx_clk_hw_pll14xx("dram_pll", "dram_pll_ref_sel", base + 0x50, &imx_1443x_dram_pll); + hws[IMX8MN_GPU_PLL] = imx_clk_hw_pll14xx("gpu_pll", "gpu_pll_ref_sel", base + 0x64, &imx_1416x_pll); +- hws[IMX8MN_VPU_PLL] = imx_clk_hw_pll14xx("vpu_pll", "vpu_pll_ref_sel", base + 0x74, &imx_1416x_pll); ++ hws[IMX8MN_M7_ALT_PLL] = imx_clk_hw_pll14xx("m7_alt_pll", "m7_alt_pll_ref_sel", base + 0x74, &imx_1416x_pll); + hws[IMX8MN_ARM_PLL] = imx_clk_hw_pll14xx("arm_pll", "arm_pll_ref_sel", base + 0x84, &imx_1416x_pll); + hws[IMX8MN_SYS_PLL1] = imx_clk_hw_fixed("sys_pll1", 800000000); + hws[IMX8MN_SYS_PLL2] = imx_clk_hw_fixed("sys_pll2", 1000000000); +@@ -370,20 +370,20 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) + /* PLL bypass out */ + hws[IMX8MN_AUDIO_PLL1_BYPASS] = imx_clk_hw_mux_flags("audio_pll1_bypass", base, 16, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT); + hws[IMX8MN_AUDIO_PLL2_BYPASS] = imx_clk_hw_mux_flags("audio_pll2_bypass", base + 0x14, 16, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT); +- hws[IMX8MN_VIDEO_PLL1_BYPASS] = imx_clk_hw_mux_flags("video_pll1_bypass", base + 0x28, 16, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels), CLK_SET_RATE_PARENT); ++ hws[IMX8MN_VIDEO_PLL_BYPASS] = imx_clk_hw_mux_flags("video_pll_bypass", base + 0x28, 16, 1, video_pll_bypass_sels, ARRAY_SIZE(video_pll_bypass_sels), CLK_SET_RATE_PARENT); + hws[IMX8MN_DRAM_PLL_BYPASS] = imx_clk_hw_mux_flags("dram_pll_bypass", base + 0x50, 16, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT); + hws[IMX8MN_GPU_PLL_BYPASS] = imx_clk_hw_mux_flags("gpu_pll_bypass", base + 0x64, 28, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT); +- hws[IMX8MN_VPU_PLL_BYPASS] = imx_clk_hw_mux_flags("vpu_pll_bypass", base + 0x74, 28, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT); ++ hws[IMX8MN_M7_ALT_PLL_BYPASS] = imx_clk_hw_mux_flags("m7_alt_pll_bypass", base + 0x74, 28, 1, m7_alt_pll_bypass_sels, ARRAY_SIZE(m7_alt_pll_bypass_sels), CLK_SET_RATE_PARENT); + hws[IMX8MN_ARM_PLL_BYPASS] = imx_clk_hw_mux_flags("arm_pll_bypass", base + 0x84, 28, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT); + hws[IMX8MN_SYS_PLL3_BYPASS] = imx_clk_hw_mux_flags("sys_pll3_bypass", base + 0x114, 28, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT); + + /* PLL out gate */ + hws[IMX8MN_AUDIO_PLL1_OUT] = imx_clk_hw_gate("audio_pll1_out", "audio_pll1_bypass", base, 13); + hws[IMX8MN_AUDIO_PLL2_OUT] = imx_clk_hw_gate("audio_pll2_out", "audio_pll2_bypass", base + 0x14, 13); +- hws[IMX8MN_VIDEO_PLL1_OUT] = imx_clk_hw_gate("video_pll1_out", "video_pll1_bypass", base + 0x28, 13); ++ hws[IMX8MN_VIDEO_PLL_OUT] = imx_clk_hw_gate("video_pll_out", "video_pll_bypass", base + 0x28, 13); + hws[IMX8MN_DRAM_PLL_OUT] = imx_clk_hw_gate("dram_pll_out", "dram_pll_bypass", base + 0x50, 13); + hws[IMX8MN_GPU_PLL_OUT] = imx_clk_hw_gate("gpu_pll_out", "gpu_pll_bypass", base + 0x64, 11); +- hws[IMX8MN_VPU_PLL_OUT] = imx_clk_hw_gate("vpu_pll_out", "vpu_pll_bypass", base + 0x74, 11); ++ hws[IMX8MN_M7_ALT_PLL_OUT] = imx_clk_hw_gate("m7_alt_pll_out", "m7_alt_pll_bypass", base + 0x74, 11); + hws[IMX8MN_ARM_PLL_OUT] = imx_clk_hw_gate("arm_pll_out", "arm_pll_bypass", base + 0x84, 11); + hws[IMX8MN_SYS_PLL3_OUT] = imx_clk_hw_gate("sys_pll3_out", "sys_pll3_bypass", base + 0x114, 11); + +diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c +index 652ae58c2735f..5d68d975b4eb1 100644 +--- a/drivers/clk/imx/clk-imx8mp.c ++++ b/drivers/clk/imx/clk-imx8mp.c +@@ -17,6 +17,7 @@ + + static u32 share_count_nand; + static u32 share_count_media; ++static u32 share_count_usb; + + static const char * const pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", }; + static const char * const audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", }; +@@ -673,7 +674,8 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) + hws[IMX8MP_CLK_UART2_ROOT] = imx_clk_hw_gate4("uart2_root_clk", "uart2", ccm_base + 0x44a0, 0); + hws[IMX8MP_CLK_UART3_ROOT] = imx_clk_hw_gate4("uart3_root_clk", "uart3", ccm_base + 0x44b0, 0); + hws[IMX8MP_CLK_UART4_ROOT] = imx_clk_hw_gate4("uart4_root_clk", "uart4", ccm_base + 0x44c0, 0); +- hws[IMX8MP_CLK_USB_ROOT] = imx_clk_hw_gate4("usb_root_clk", "hsio_axi", ccm_base + 0x44d0, 0); ++ hws[IMX8MP_CLK_USB_ROOT] = imx_clk_hw_gate2_shared2("usb_root_clk", "hsio_axi", ccm_base + 0x44d0, 0, &share_count_usb); ++ hws[IMX8MP_CLK_USB_SUSP] = imx_clk_hw_gate2_shared2("usb_suspend_clk", "osc_32k", ccm_base + 0x44d0, 0, &share_count_usb); + hws[IMX8MP_CLK_USB_PHY_ROOT] = imx_clk_hw_gate4("usb_phy_root_clk", "usb_phy_ref", ccm_base + 0x44f0, 0); + hws[IMX8MP_CLK_USDHC1_ROOT] = imx_clk_hw_gate4("usdhc1_root_clk", "usdhc1", ccm_base + 0x4510, 0); + hws[IMX8MP_CLK_USDHC2_ROOT] = imx_clk_hw_gate4("usdhc2_root_clk", "usdhc2", ccm_base + 0x4520, 0); +diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c +index 99cff1fd108b5..02d6a9894521d 100644 +--- a/drivers/clk/imx/clk-imx93.c ++++ b/drivers/clk/imx/clk-imx93.c +@@ -170,7 +170,7 @@ static const struct imx93_clk_ccgr { + { IMX93_CLK_MU2_B_GATE, "mu2_b", "bus_wakeup_root", 0x8500, 0, &share_count_mub }, + { IMX93_CLK_EDMA1_GATE, "edma1", "m33_root", 0x8540, }, + { IMX93_CLK_EDMA2_GATE, "edma2", "wakeup_axi_root", 0x8580, }, +- { IMX93_CLK_FLEXSPI1_GATE, "flexspi", "flexspi_root", 0x8640, }, ++ { IMX93_CLK_FLEXSPI1_GATE, "flexspi1", "flexspi1_root", 0x8640, }, + { IMX93_CLK_GPIO1_GATE, "gpio1", "m33_root", 0x8880, }, + { IMX93_CLK_GPIO2_GATE, "gpio2", "bus_wakeup_root", 0x88c0, }, + { IMX93_CLK_GPIO3_GATE, "gpio3", "bus_wakeup_root", 0x8900, }, +@@ -240,7 +240,7 @@ static const struct imx93_clk_ccgr { + { IMX93_CLK_AUD_XCVR_GATE, "aud_xcvr", "audio_xcvr_root", 0x9b80, }, + { IMX93_CLK_SPDIF_GATE, "spdif", "spdif_root", 0x9c00, }, + { IMX93_CLK_HSIO_32K_GATE, "hsio_32k", "osc_32k", 0x9dc0, }, +- { IMX93_CLK_ENET1_GATE, "enet1", "enet_root", 0x9e00, }, ++ { IMX93_CLK_ENET1_GATE, "enet1", "wakeup_axi_root", 0x9e00, }, + { IMX93_CLK_ENET_QOS_GATE, "enet_qos", "wakeup_axi_root", 0x9e40, }, + { IMX93_CLK_SYS_CNT_GATE, "sys_cnt", "osc_24m", 0x9e80, }, + { IMX93_CLK_TSTMR1_GATE, "tstmr1", "bus_aon_root", 0x9ec0, }, +@@ -258,7 +258,7 @@ static int imx93_clocks_probe(struct platform_device *pdev) + struct device_node *np = dev->of_node; + const struct imx93_clk_root *root; + const struct imx93_clk_ccgr *ccgr; +- void __iomem *base = NULL; ++ void __iomem *base, *anatop_base; + int i, ret; + + clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, +@@ -285,20 +285,22 @@ static int imx93_clocks_probe(struct platform_device *pdev) + "sys_pll_pfd2", 1, 2); + + np = of_find_compatible_node(NULL, NULL, "fsl,imx93-anatop"); +- base = of_iomap(np, 0); ++ anatop_base = of_iomap(np, 0); + of_node_put(np); +- if (WARN_ON(!base)) ++ if (WARN_ON(!anatop_base)) + return -ENOMEM; + +- clks[IMX93_CLK_AUDIO_PLL] = imx_clk_fracn_gppll("audio_pll", "osc_24m", base + 0x1200, ++ clks[IMX93_CLK_AUDIO_PLL] = imx_clk_fracn_gppll("audio_pll", "osc_24m", anatop_base + 0x1200, + &imx_fracn_gppll); +- clks[IMX93_CLK_VIDEO_PLL] = imx_clk_fracn_gppll("video_pll", "osc_24m", base + 0x1400, ++ clks[IMX93_CLK_VIDEO_PLL] = imx_clk_fracn_gppll("video_pll", "osc_24m", anatop_base + 0x1400, + &imx_fracn_gppll); + + np = dev->of_node; + base = devm_platform_ioremap_resource(pdev, 0); +- if (WARN_ON(IS_ERR(base))) ++ if (WARN_ON(IS_ERR(base))) { ++ iounmap(anatop_base); + return PTR_ERR(base); ++ } + + for (i = 0; i < ARRAY_SIZE(root_array); i++) { + root = &root_array[i]; +@@ -327,6 +329,7 @@ static int imx93_clocks_probe(struct platform_device *pdev) + + unregister_hws: + imx_unregister_hw_clocks(clks, IMX93_CLK_END); ++ iounmap(anatop_base); + + return ret; + } +diff --git a/drivers/clk/imx/clk-imxrt1050.c b/drivers/clk/imx/clk-imxrt1050.c +index 9539d35588ee9..26108e9f7e67a 100644 +--- a/drivers/clk/imx/clk-imxrt1050.c ++++ b/drivers/clk/imx/clk-imxrt1050.c +@@ -140,7 +140,7 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev) + hws[IMXRT1050_CLK_USDHC1] = imx_clk_hw_gate2("usdhc1", "usdhc1_podf", ccm_base + 0x80, 2); + hws[IMXRT1050_CLK_USDHC2] = imx_clk_hw_gate2("usdhc2", "usdhc2_podf", ccm_base + 0x80, 4); + hws[IMXRT1050_CLK_LPUART1] = imx_clk_hw_gate2("lpuart1", "lpuart_podf", ccm_base + 0x7c, 24); +- hws[IMXRT1050_CLK_LCDIF_APB] = imx_clk_hw_gate2("lcdif", "lcdif_podf", ccm_base + 0x74, 10); ++ hws[IMXRT1050_CLK_LCDIF_APB] = imx_clk_hw_gate2("lcdif", "lcdif_podf", ccm_base + 0x70, 28); + hws[IMXRT1050_CLK_DMA] = imx_clk_hw_gate("dma", "ipg", ccm_base + 0x7C, 6); + hws[IMXRT1050_CLK_DMA_MUX] = imx_clk_hw_gate("dmamux0", "ipg", ccm_base + 0x7C, 7); + imx_check_clk_hws(hws, IMXRT1050_CLK_END); +diff --git a/drivers/clk/mediatek/clk-mt7986-infracfg.c b/drivers/clk/mediatek/clk-mt7986-infracfg.c +index d90727a53283c..49666047bf0ed 100644 +--- a/drivers/clk/mediatek/clk-mt7986-infracfg.c ++++ b/drivers/clk/mediatek/clk-mt7986-infracfg.c +@@ -153,7 +153,7 @@ static const struct mtk_gate infra_clks[] = { + 18), + GATE_INFRA1(CLK_INFRA_MSDC_66M_CK, "infra_msdc_66m", "infra_sysaxi_d2", + 19), +- GATE_INFRA1(CLK_INFRA_ADC_26M_CK, "infra_adc_26m", "csw_f26m_sel", 20), ++ GATE_INFRA1(CLK_INFRA_ADC_26M_CK, "infra_adc_26m", "infra_adc_frc", 20), + GATE_INFRA1(CLK_INFRA_ADC_FRC_CK, "infra_adc_frc", "csw_f26m_sel", 21), + GATE_INFRA1(CLK_INFRA_FBIST2FPC_CK, "infra_fbist2fpc", "nfi1x_sel", 23), + /* INFRA2 */ +diff --git a/drivers/clk/microchip/clk-mpfs-ccc.c b/drivers/clk/microchip/clk-mpfs-ccc.c +index 7be028dced63d..32aae880a14f3 100644 +--- a/drivers/clk/microchip/clk-mpfs-ccc.c ++++ b/drivers/clk/microchip/clk-mpfs-ccc.c +@@ -166,6 +166,9 @@ static int mpfs_ccc_register_outputs(struct device *dev, struct mpfs_ccc_out_hw_ + struct mpfs_ccc_out_hw_clock *out_hw = &out_hws[i]; + char *name = devm_kzalloc(dev, 23, GFP_KERNEL); + ++ if (!name) ++ return -ENOMEM; ++ + snprintf(name, 23, "%s_out%u", parent->name, i); + out_hw->divider.hw.init = CLK_HW_INIT_HW(name, &parent->hw, &clk_divider_ops, 0); + out_hw->divider.reg = data->pll_base[i / MPFS_CCC_OUTPUTS_PER_PLL] + +@@ -200,6 +203,9 @@ static int mpfs_ccc_register_plls(struct device *dev, struct mpfs_ccc_pll_hw_clo + struct mpfs_ccc_pll_hw_clock *pll_hw = &pll_hws[i]; + char *name = devm_kzalloc(dev, 18, GFP_KERNEL); + ++ if (!name) ++ return -ENOMEM; ++ + pll_hw->base = data->pll_base[i]; + snprintf(name, 18, "ccc%s_pll%u", strchrnul(dev->of_node->full_name, '@'), i); + pll_hw->name = (const char *)name; +diff --git a/drivers/clk/qcom/clk-krait.c b/drivers/clk/qcom/clk-krait.c +index 45da736bd5f4c..293a9dfa7151a 100644 +--- a/drivers/clk/qcom/clk-krait.c ++++ b/drivers/clk/qcom/clk-krait.c +@@ -114,6 +114,8 @@ static int krait_div2_set_rate(struct clk_hw *hw, unsigned long rate, + + if (d->lpl) + mask = mask << (d->shift + LPL_SHIFT) | mask << d->shift; ++ else ++ mask <<= d->shift; + + spin_lock_irqsave(&krait_clock_reg_lock, flags); + val = krait_get_l2_indirect_reg(d->offset); +diff --git a/drivers/clk/qcom/dispcc-sm6350.c b/drivers/clk/qcom/dispcc-sm6350.c +index 0c3c2e26ede90..ea6f54ed846ec 100644 +--- a/drivers/clk/qcom/dispcc-sm6350.c ++++ b/drivers/clk/qcom/dispcc-sm6350.c +@@ -306,7 +306,7 @@ static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src = { + .name = "disp_cc_mdss_pclk0_clk_src", + .parent_data = disp_cc_parent_data_5, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_5), +- .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, ++ .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE | CLK_OPS_PARENT_ENABLE, + .ops = &clk_pixel_ops, + }, + }; +@@ -385,7 +385,7 @@ static struct clk_branch disp_cc_mdss_byte0_clk = { + &disp_cc_mdss_byte0_clk_src.clkr.hw, + }, + .num_parents = 1, +- .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, ++ .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE | CLK_OPS_PARENT_ENABLE, + .ops = &clk_branch2_ops, + }, + }, +diff --git a/drivers/clk/qcom/gcc-ipq806x.c b/drivers/clk/qcom/gcc-ipq806x.c +index 718de17a1e600..6447f3e81b555 100644 +--- a/drivers/clk/qcom/gcc-ipq806x.c ++++ b/drivers/clk/qcom/gcc-ipq806x.c +@@ -79,7 +79,9 @@ static struct clk_regmap pll4_vote = { + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "pll4_vote", +- .parent_names = (const char *[]){ "pll4" }, ++ .parent_data = &(const struct clk_parent_data){ ++ .fw_name = "pll4", .name = "pll4", ++ }, + .num_parents = 1, + .ops = &clk_pll_vote_ops, + }, +diff --git a/drivers/clk/qcom/gcc-sm8250.c b/drivers/clk/qcom/gcc-sm8250.c +index 9755ef4888c19..a0ba37656b07b 100644 +--- a/drivers/clk/qcom/gcc-sm8250.c ++++ b/drivers/clk/qcom/gcc-sm8250.c +@@ -3267,7 +3267,7 @@ static struct gdsc usb30_prim_gdsc = { + .pd = { + .name = "usb30_prim_gdsc", + }, +- .pwrsts = PWRSTS_OFF_ON, ++ .pwrsts = PWRSTS_RET_ON, + }; + + static struct gdsc usb30_sec_gdsc = { +@@ -3275,7 +3275,7 @@ static struct gdsc usb30_sec_gdsc = { + .pd = { + .name = "usb30_sec_gdsc", + }, +- .pwrsts = PWRSTS_OFF_ON, ++ .pwrsts = PWRSTS_RET_ON, + }; + + static struct gdsc hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc = { +diff --git a/drivers/clk/qcom/lpassaudiocc-sc7280.c b/drivers/clk/qcom/lpassaudiocc-sc7280.c +index 063e0365f3119..1339f9211a149 100644 +--- a/drivers/clk/qcom/lpassaudiocc-sc7280.c ++++ b/drivers/clk/qcom/lpassaudiocc-sc7280.c +@@ -722,33 +722,17 @@ static const struct of_device_id lpass_audio_cc_sc7280_match_table[] = { + }; + MODULE_DEVICE_TABLE(of, lpass_audio_cc_sc7280_match_table); + +-static void lpassaudio_pm_runtime_disable(void *data) +-{ +- pm_runtime_disable(data); +-} +- +-static void lpassaudio_pm_clk_destroy(void *data) +-{ +- pm_clk_destroy(data); +-} +- +-static int lpassaudio_create_pm_clks(struct platform_device *pdev) ++static int lpass_audio_setup_runtime_pm(struct platform_device *pdev) + { + int ret; + + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, 50); +- pm_runtime_enable(&pdev->dev); +- +- ret = devm_add_action_or_reset(&pdev->dev, lpassaudio_pm_runtime_disable, &pdev->dev); +- if (ret) +- return ret; +- +- ret = pm_clk_create(&pdev->dev); ++ ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; + +- ret = devm_add_action_or_reset(&pdev->dev, lpassaudio_pm_clk_destroy, &pdev->dev); ++ ret = devm_pm_clk_create(&pdev->dev); + if (ret) + return ret; + +@@ -756,7 +740,7 @@ static int lpassaudio_create_pm_clks(struct platform_device *pdev) + if (ret < 0) + dev_err(&pdev->dev, "failed to acquire iface clock\n"); + +- return ret; ++ return pm_runtime_resume_and_get(&pdev->dev); + } + + static int lpass_audio_cc_sc7280_probe(struct platform_device *pdev) +@@ -765,7 +749,7 @@ static int lpass_audio_cc_sc7280_probe(struct platform_device *pdev) + struct regmap *regmap; + int ret; + +- ret = lpassaudio_create_pm_clks(pdev); ++ ret = lpass_audio_setup_runtime_pm(pdev); + if (ret) + return ret; + +@@ -775,8 +759,8 @@ static int lpass_audio_cc_sc7280_probe(struct platform_device *pdev) + + regmap = qcom_cc_map(pdev, desc); + if (IS_ERR(regmap)) { +- pm_runtime_disable(&pdev->dev); +- return PTR_ERR(regmap); ++ ret = PTR_ERR(regmap); ++ goto exit; + } + + clk_zonda_pll_configure(&lpass_audio_cc_pll, regmap, &lpass_audio_cc_pll_config); +@@ -788,20 +772,18 @@ static int lpass_audio_cc_sc7280_probe(struct platform_device *pdev) + ret = qcom_cc_really_probe(pdev, &lpass_audio_cc_sc7280_desc, regmap); + if (ret) { + dev_err(&pdev->dev, "Failed to register LPASS AUDIO CC clocks\n"); +- pm_runtime_disable(&pdev->dev); +- return ret; ++ goto exit; + } + + ret = qcom_cc_probe_by_index(pdev, 1, &lpass_audio_cc_reset_sc7280_desc); + if (ret) { + dev_err(&pdev->dev, "Failed to register LPASS AUDIO CC Resets\n"); +- pm_runtime_disable(&pdev->dev); +- return ret; ++ goto exit; + } + + pm_runtime_mark_last_busy(&pdev->dev); ++exit: + pm_runtime_put_autosuspend(&pdev->dev); +- pm_runtime_put_sync(&pdev->dev); + + return ret; + } +@@ -839,14 +821,15 @@ static int lpass_aon_cc_sc7280_probe(struct platform_device *pdev) + struct regmap *regmap; + int ret; + +- ret = lpassaudio_create_pm_clks(pdev); ++ ret = lpass_audio_setup_runtime_pm(pdev); + if (ret) + return ret; + + if (of_property_read_bool(pdev->dev.of_node, "qcom,adsp-pil-mode")) { + lpass_audio_cc_sc7280_regmap_config.name = "cc"; + desc = &lpass_cc_sc7280_desc; +- return qcom_cc_probe(pdev, desc); ++ ret = qcom_cc_probe(pdev, desc); ++ goto exit; + } + + lpass_audio_cc_sc7280_regmap_config.name = "lpasscc_aon"; +@@ -854,18 +837,22 @@ static int lpass_aon_cc_sc7280_probe(struct platform_device *pdev) + desc = &lpass_aon_cc_sc7280_desc; + + regmap = qcom_cc_map(pdev, desc); +- if (IS_ERR(regmap)) +- return PTR_ERR(regmap); ++ if (IS_ERR(regmap)) { ++ ret = PTR_ERR(regmap); ++ goto exit; ++ } + + clk_lucid_pll_configure(&lpass_aon_cc_pll, regmap, &lpass_aon_cc_pll_config); + + ret = qcom_cc_really_probe(pdev, &lpass_aon_cc_sc7280_desc, regmap); +- if (ret) ++ if (ret) { + dev_err(&pdev->dev, "Failed to register LPASS AON CC clocks\n"); ++ goto exit; ++ } + + pm_runtime_mark_last_busy(&pdev->dev); ++exit: + pm_runtime_put_autosuspend(&pdev->dev); +- pm_runtime_put_sync(&pdev->dev); + + return ret; + } +diff --git a/drivers/clk/qcom/lpasscorecc-sc7180.c b/drivers/clk/qcom/lpasscorecc-sc7180.c +index ac09b7b840aba..a5731994cbed1 100644 +--- a/drivers/clk/qcom/lpasscorecc-sc7180.c ++++ b/drivers/clk/qcom/lpasscorecc-sc7180.c +@@ -356,7 +356,7 @@ static const struct qcom_cc_desc lpass_audio_hm_sc7180_desc = { + .num_gdscs = ARRAY_SIZE(lpass_audio_hm_sc7180_gdscs), + }; + +-static int lpass_create_pm_clks(struct platform_device *pdev) ++static int lpass_setup_runtime_pm(struct platform_device *pdev) + { + int ret; + +@@ -375,7 +375,7 @@ static int lpass_create_pm_clks(struct platform_device *pdev) + if (ret < 0) + dev_err(&pdev->dev, "failed to acquire iface clock\n"); + +- return ret; ++ return pm_runtime_resume_and_get(&pdev->dev); + } + + static int lpass_core_cc_sc7180_probe(struct platform_device *pdev) +@@ -384,7 +384,7 @@ static int lpass_core_cc_sc7180_probe(struct platform_device *pdev) + struct regmap *regmap; + int ret; + +- ret = lpass_create_pm_clks(pdev); ++ ret = lpass_setup_runtime_pm(pdev); + if (ret) + return ret; + +@@ -392,12 +392,14 @@ static int lpass_core_cc_sc7180_probe(struct platform_device *pdev) + desc = &lpass_audio_hm_sc7180_desc; + ret = qcom_cc_probe_by_index(pdev, 1, desc); + if (ret) +- return ret; ++ goto exit; + + lpass_core_cc_sc7180_regmap_config.name = "lpass_core_cc"; + regmap = qcom_cc_map(pdev, &lpass_core_cc_sc7180_desc); +- if (IS_ERR(regmap)) +- return PTR_ERR(regmap); ++ if (IS_ERR(regmap)) { ++ ret = PTR_ERR(regmap); ++ goto exit; ++ } + + /* + * Keep the CLK always-ON +@@ -415,6 +417,7 @@ static int lpass_core_cc_sc7180_probe(struct platform_device *pdev) + ret = qcom_cc_really_probe(pdev, &lpass_core_cc_sc7180_desc, regmap); + + pm_runtime_mark_last_busy(&pdev->dev); ++exit: + pm_runtime_put_autosuspend(&pdev->dev); + + return ret; +@@ -425,14 +428,19 @@ static int lpass_hm_core_probe(struct platform_device *pdev) + const struct qcom_cc_desc *desc; + int ret; + +- ret = lpass_create_pm_clks(pdev); ++ ret = lpass_setup_runtime_pm(pdev); + if (ret) + return ret; + + lpass_core_cc_sc7180_regmap_config.name = "lpass_hm_core"; + desc = &lpass_core_hm_sc7180_desc; + +- return qcom_cc_probe_by_index(pdev, 0, desc); ++ ret = qcom_cc_probe_by_index(pdev, 0, desc); ++ ++ pm_runtime_mark_last_busy(&pdev->dev); ++ pm_runtime_put_autosuspend(&pdev->dev); ++ ++ return ret; + } + + static const struct of_device_id lpass_hm_sc7180_match_table[] = { +diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c +index d74d46833012f..e02542ca24a06 100644 +--- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c +@@ -116,7 +116,7 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { + DEF_FIXED("cp", R8A779A0_CLK_CP, CLK_EXTAL, 2, 1), + DEF_FIXED("cl16mck", R8A779A0_CLK_CL16MCK, CLK_PLL1_DIV2, 64, 1), + +- DEF_GEN4_SDH("sdh0", R8A779A0_CLK_SD0H, CLK_SDSRC, 0x870), ++ DEF_GEN4_SDH("sd0h", R8A779A0_CLK_SD0H, CLK_SDSRC, 0x870), + DEF_GEN4_SD("sd0", R8A779A0_CLK_SD0, R8A779A0_CLK_SD0H, 0x870), + + DEF_BASE("rpc", R8A779A0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC), +diff --git a/drivers/clk/renesas/r8a779f0-cpg-mssr.c b/drivers/clk/renesas/r8a779f0-cpg-mssr.c +index 4baf355e26d88..27b668def357f 100644 +--- a/drivers/clk/renesas/r8a779f0-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a779f0-cpg-mssr.c +@@ -113,7 +113,7 @@ static const struct cpg_core_clk r8a779f0_core_clks[] __initconst = { + DEF_FIXED("sasyncperd2", R8A779F0_CLK_SASYNCPERD2, R8A779F0_CLK_SASYNCPERD1, 2, 1), + DEF_FIXED("sasyncperd4", R8A779F0_CLK_SASYNCPERD4, R8A779F0_CLK_SASYNCPERD1, 4, 1), + +- DEF_GEN4_SDH("sdh0", R8A779F0_CLK_SD0H, CLK_SDSRC, 0x870), ++ DEF_GEN4_SDH("sd0h", R8A779F0_CLK_SD0H, CLK_SDSRC, 0x870), + DEF_GEN4_SD("sd0", R8A779F0_CLK_SD0, R8A779F0_CLK_SD0H, 0x870), + + DEF_BASE("rpc", R8A779F0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC), +@@ -126,10 +126,10 @@ static const struct cpg_core_clk r8a779f0_core_clks[] __initconst = { + }; + + static const struct mssr_mod_clk r8a779f0_mod_clks[] __initconst = { +- DEF_MOD("hscif0", 514, R8A779F0_CLK_S0D3), +- DEF_MOD("hscif1", 515, R8A779F0_CLK_S0D3), +- DEF_MOD("hscif2", 516, R8A779F0_CLK_S0D3), +- DEF_MOD("hscif3", 517, R8A779F0_CLK_S0D3), ++ DEF_MOD("hscif0", 514, R8A779F0_CLK_SASYNCPERD1), ++ DEF_MOD("hscif1", 515, R8A779F0_CLK_SASYNCPERD1), ++ DEF_MOD("hscif2", 516, R8A779F0_CLK_SASYNCPERD1), ++ DEF_MOD("hscif3", 517, R8A779F0_CLK_SASYNCPERD1), + DEF_MOD("i2c0", 518, R8A779F0_CLK_S0D6_PER), + DEF_MOD("i2c1", 519, R8A779F0_CLK_S0D6_PER), + DEF_MOD("i2c2", 520, R8A779F0_CLK_S0D6_PER), +@@ -142,10 +142,10 @@ static const struct mssr_mod_clk r8a779f0_mod_clks[] __initconst = { + DEF_MOD("msiof3", 621, R8A779F0_CLK_MSO), + DEF_MOD("pcie0", 624, R8A779F0_CLK_S0D2), + DEF_MOD("pcie1", 625, R8A779F0_CLK_S0D2), +- DEF_MOD("scif0", 702, R8A779F0_CLK_S0D12_PER), +- DEF_MOD("scif1", 703, R8A779F0_CLK_S0D12_PER), +- DEF_MOD("scif3", 704, R8A779F0_CLK_S0D12_PER), +- DEF_MOD("scif4", 705, R8A779F0_CLK_S0D12_PER), ++ DEF_MOD("scif0", 702, R8A779F0_CLK_SASYNCPERD4), ++ DEF_MOD("scif1", 703, R8A779F0_CLK_SASYNCPERD4), ++ DEF_MOD("scif3", 704, R8A779F0_CLK_SASYNCPERD4), ++ DEF_MOD("scif4", 705, R8A779F0_CLK_SASYNCPERD4), + DEF_MOD("sdhi0", 706, R8A779F0_CLK_SD0), + DEF_MOD("sys-dmac0", 709, R8A779F0_CLK_S0D3_PER), + DEF_MOD("sys-dmac1", 710, R8A779F0_CLK_S0D3_PER), +diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c +index 1488c9d6e6394..983faa5707b9c 100644 +--- a/drivers/clk/renesas/r9a06g032-clocks.c ++++ b/drivers/clk/renesas/r9a06g032-clocks.c +@@ -412,7 +412,7 @@ static int r9a06g032_attach_dev(struct generic_pm_domain *pd, + int error; + int index; + +- while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, ++ while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i++, + &clkspec)) { + if (clkspec.np != pd->dev.of_node) + continue; +@@ -425,7 +425,6 @@ static int r9a06g032_attach_dev(struct generic_pm_domain *pd, + if (error) + return error; + } +- i++; + } + + return 0; +diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c +index f7827b3b7fc1c..6e5e502be44a6 100644 +--- a/drivers/clk/rockchip/clk-pll.c ++++ b/drivers/clk/rockchip/clk-pll.c +@@ -981,6 +981,7 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, + return mux_clk; + + err_pll: ++ kfree(pll->rate_table); + clk_unregister(mux_clk); + mux_clk = pll_clk; + err_mux: +diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c +index fe383471c5f0a..0ff28938943f0 100644 +--- a/drivers/clk/samsung/clk-pll.c ++++ b/drivers/clk/samsung/clk-pll.c +@@ -1583,6 +1583,7 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, + if (ret) { + pr_err("%s: failed to register pll clock %s : %d\n", + __func__, pll_clk->name, ret); ++ kfree(pll->rate_table); + kfree(pll); + return; + } +diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c +index 53d6e3ec4309f..c94b59b80dd43 100644 +--- a/drivers/clk/socfpga/clk-gate.c ++++ b/drivers/clk/socfpga/clk-gate.c +@@ -188,8 +188,10 @@ void __init socfpga_gate_init(struct device_node *node) + return; + + ops = kmemdup(&gateclk_ops, sizeof(gateclk_ops), GFP_KERNEL); +- if (WARN_ON(!ops)) ++ if (WARN_ON(!ops)) { ++ kfree(socfpga_clk); + return; ++ } + + rc = of_property_read_u32_array(node, "clk-gate", clk_gate, 2); + if (rc) +@@ -243,6 +245,7 @@ void __init socfpga_gate_init(struct device_node *node) + + err = clk_hw_register(NULL, hw_clk); + if (err) { ++ kfree(ops); + kfree(socfpga_clk); + return; + } +diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c +index d820292a381d0..40df1db102a77 100644 +--- a/drivers/clk/st/clkgen-fsyn.c ++++ b/drivers/clk/st/clkgen-fsyn.c +@@ -1020,9 +1020,10 @@ static void __init st_of_quadfs_setup(struct device_node *np, + + clk = st_clk_register_quadfs_pll(pll_name, clk_parent_name, datac->data, + reg, lock); +- if (IS_ERR(clk)) ++ if (IS_ERR(clk)) { ++ kfree(lock); + goto err_exit; +- else ++ } else + pr_debug("%s: parent %s rate %u\n", + __clk_get_name(clk), + __clk_get_name(clk_get_parent(clk)), +diff --git a/drivers/clk/visconti/pll.c b/drivers/clk/visconti/pll.c +index a484cb945d67b..1f3234f226674 100644 +--- a/drivers/clk/visconti/pll.c ++++ b/drivers/clk/visconti/pll.c +@@ -277,6 +277,7 @@ static struct clk_hw *visconti_register_pll(struct visconti_pll_provider *ctx, + ret = clk_hw_register(NULL, &pll->hw); + if (ret) { + pr_err("failed to register pll clock %s : %d\n", name, ret); ++ kfree(pll->rate_table); + kfree(pll); + pll_hw_clk = ERR_PTR(ret); + } +diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c +index 64dcb082d4cf6..7b952aa52c0b9 100644 +--- a/drivers/clocksource/sh_cmt.c ++++ b/drivers/clocksource/sh_cmt.c +@@ -13,6 +13,7 @@ + #include <linux/init.h> + #include <linux/interrupt.h> + #include <linux/io.h> ++#include <linux/iopoll.h> + #include <linux/ioport.h> + #include <linux/irq.h> + #include <linux/module.h> +@@ -116,6 +117,7 @@ struct sh_cmt_device { + void __iomem *mapbase; + struct clk *clk; + unsigned long rate; ++ unsigned int reg_delay; + + raw_spinlock_t lock; /* Protect the shared start/stop register */ + +@@ -247,10 +249,17 @@ static inline u32 sh_cmt_read_cmstr(struct sh_cmt_channel *ch) + + static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch, u32 value) + { +- if (ch->iostart) +- ch->cmt->info->write_control(ch->iostart, 0, value); +- else +- ch->cmt->info->write_control(ch->cmt->mapbase, 0, value); ++ u32 old_value = sh_cmt_read_cmstr(ch); ++ ++ if (value != old_value) { ++ if (ch->iostart) { ++ ch->cmt->info->write_control(ch->iostart, 0, value); ++ udelay(ch->cmt->reg_delay); ++ } else { ++ ch->cmt->info->write_control(ch->cmt->mapbase, 0, value); ++ udelay(ch->cmt->reg_delay); ++ } ++ } + } + + static inline u32 sh_cmt_read_cmcsr(struct sh_cmt_channel *ch) +@@ -260,7 +269,12 @@ static inline u32 sh_cmt_read_cmcsr(struct sh_cmt_channel *ch) + + static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch, u32 value) + { +- ch->cmt->info->write_control(ch->ioctrl, CMCSR, value); ++ u32 old_value = sh_cmt_read_cmcsr(ch); ++ ++ if (value != old_value) { ++ ch->cmt->info->write_control(ch->ioctrl, CMCSR, value); ++ udelay(ch->cmt->reg_delay); ++ } + } + + static inline u32 sh_cmt_read_cmcnt(struct sh_cmt_channel *ch) +@@ -268,14 +282,33 @@ static inline u32 sh_cmt_read_cmcnt(struct sh_cmt_channel *ch) + return ch->cmt->info->read_count(ch->ioctrl, CMCNT); + } + +-static inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch, u32 value) ++static inline int sh_cmt_write_cmcnt(struct sh_cmt_channel *ch, u32 value) + { ++ /* Tests showed that we need to wait 3 clocks here */ ++ unsigned int cmcnt_delay = DIV_ROUND_UP(3 * ch->cmt->reg_delay, 2); ++ u32 reg; ++ ++ if (ch->cmt->info->model > SH_CMT_16BIT) { ++ int ret = read_poll_timeout_atomic(sh_cmt_read_cmcsr, reg, ++ !(reg & SH_CMT32_CMCSR_WRFLG), ++ 1, cmcnt_delay, false, ch); ++ if (ret < 0) ++ return ret; ++ } ++ + ch->cmt->info->write_count(ch->ioctrl, CMCNT, value); ++ udelay(cmcnt_delay); ++ return 0; + } + + static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch, u32 value) + { +- ch->cmt->info->write_count(ch->ioctrl, CMCOR, value); ++ u32 old_value = ch->cmt->info->read_count(ch->ioctrl, CMCOR); ++ ++ if (value != old_value) { ++ ch->cmt->info->write_count(ch->ioctrl, CMCOR, value); ++ udelay(ch->cmt->reg_delay); ++ } + } + + static u32 sh_cmt_get_counter(struct sh_cmt_channel *ch, u32 *has_wrapped) +@@ -319,7 +352,7 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start) + + static int sh_cmt_enable(struct sh_cmt_channel *ch) + { +- int k, ret; ++ int ret; + + dev_pm_syscore_device(&ch->cmt->pdev->dev, true); + +@@ -347,26 +380,9 @@ static int sh_cmt_enable(struct sh_cmt_channel *ch) + } + + sh_cmt_write_cmcor(ch, 0xffffffff); +- sh_cmt_write_cmcnt(ch, 0); +- +- /* +- * According to the sh73a0 user's manual, as CMCNT can be operated +- * only by the RCLK (Pseudo 32 kHz), there's one restriction on +- * modifying CMCNT register; two RCLK cycles are necessary before +- * this register is either read or any modification of the value +- * it holds is reflected in the LSI's actual operation. +- * +- * While at it, we're supposed to clear out the CMCNT as of this +- * moment, so make sure it's processed properly here. This will +- * take RCLKx2 at maximum. +- */ +- for (k = 0; k < 100; k++) { +- if (!sh_cmt_read_cmcnt(ch)) +- break; +- udelay(1); +- } ++ ret = sh_cmt_write_cmcnt(ch, 0); + +- if (sh_cmt_read_cmcnt(ch)) { ++ if (ret || sh_cmt_read_cmcnt(ch)) { + dev_err(&ch->cmt->pdev->dev, "ch%u: cannot clear CMCNT\n", + ch->index); + ret = -ETIMEDOUT; +@@ -995,8 +1011,8 @@ MODULE_DEVICE_TABLE(of, sh_cmt_of_table); + + static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev) + { +- unsigned int mask; +- unsigned int i; ++ unsigned int mask, i; ++ unsigned long rate; + int ret; + + cmt->pdev = pdev; +@@ -1032,10 +1048,16 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev) + if (ret < 0) + goto err_clk_unprepare; + +- if (cmt->info->width == 16) +- cmt->rate = clk_get_rate(cmt->clk) / 512; +- else +- cmt->rate = clk_get_rate(cmt->clk) / 8; ++ rate = clk_get_rate(cmt->clk); ++ if (!rate) { ++ ret = -EINVAL; ++ goto err_clk_disable; ++ } ++ ++ /* We shall wait 2 input clks after register writes */ ++ if (cmt->info->model >= SH_CMT_48BIT) ++ cmt->reg_delay = DIV_ROUND_UP(2UL * USEC_PER_SEC, rate); ++ cmt->rate = rate / (cmt->info->width == 16 ? 512 : 8); + + /* Map the memory resource(s). */ + ret = sh_cmt_map_memory(cmt); +diff --git a/drivers/clocksource/timer-ti-dm-systimer.c b/drivers/clocksource/timer-ti-dm-systimer.c +index 2737407ff0698..632523c1232f6 100644 +--- a/drivers/clocksource/timer-ti-dm-systimer.c ++++ b/drivers/clocksource/timer-ti-dm-systimer.c +@@ -345,8 +345,10 @@ static int __init dmtimer_systimer_init_clock(struct dmtimer_systimer *t, + return error; + + r = clk_get_rate(clock); +- if (!r) ++ if (!r) { ++ clk_disable_unprepare(clock); + return -ENODEV; ++ } + + if (is_ick) + t->ick = clock; +diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c +index cad29ded3a48f..00af1a8e34fbd 100644 +--- a/drivers/clocksource/timer-ti-dm.c ++++ b/drivers/clocksource/timer-ti-dm.c +@@ -1258,7 +1258,7 @@ static struct platform_driver omap_dm_timer_driver = { + .remove = omap_dm_timer_remove, + .driver = { + .name = "omap_timer", +- .of_match_table = of_match_ptr(omap_timer_match), ++ .of_match_table = omap_timer_match, + .pm = &omap_dm_timer_pm_ops, + }, + }; +diff --git a/drivers/counter/stm32-lptimer-cnt.c b/drivers/counter/stm32-lptimer-cnt.c +index d6b80b6dfc287..8439755559b21 100644 +--- a/drivers/counter/stm32-lptimer-cnt.c ++++ b/drivers/counter/stm32-lptimer-cnt.c +@@ -69,7 +69,7 @@ static int stm32_lptim_set_enable_state(struct stm32_lptim_cnt *priv, + + /* ensure CMP & ARR registers are properly written */ + ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val, +- (val & STM32_LPTIM_CMPOK_ARROK), ++ (val & STM32_LPTIM_CMPOK_ARROK) == STM32_LPTIM_CMPOK_ARROK, + 100, 1000); + if (ret) + return ret; +diff --git a/drivers/cpufreq/amd_freq_sensitivity.c b/drivers/cpufreq/amd_freq_sensitivity.c +index 6448e03bcf488..59b19b9975e8c 100644 +--- a/drivers/cpufreq/amd_freq_sensitivity.c ++++ b/drivers/cpufreq/amd_freq_sensitivity.c +@@ -125,6 +125,8 @@ static int __init amd_freq_sensitivity_init(void) + if (!pcidev) { + if (!boot_cpu_has(X86_FEATURE_PROC_FEEDBACK)) + return -ENODEV; ++ } else { ++ pci_dev_put(pcidev); + } + + if (rdmsrl_safe(MSR_AMD64_FREQ_SENSITIVITY_ACTUAL, &val)) +diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c +index 833589bc95e40..3c623a0bc147f 100644 +--- a/drivers/cpufreq/qcom-cpufreq-hw.c ++++ b/drivers/cpufreq/qcom-cpufreq-hw.c +@@ -125,7 +125,35 @@ static int qcom_cpufreq_hw_target_index(struct cpufreq_policy *policy, + return 0; + } + ++static unsigned long qcom_lmh_get_throttle_freq(struct qcom_cpufreq_data *data) ++{ ++ unsigned int lval; ++ ++ if (data->soc_data->reg_current_vote) ++ lval = readl_relaxed(data->base + data->soc_data->reg_current_vote) & 0x3ff; ++ else ++ lval = readl_relaxed(data->base + data->soc_data->reg_domain_state) & 0xff; ++ ++ return lval * xo_rate; ++} ++ ++/* Get the current frequency of the CPU (after throttling) */ + static unsigned int qcom_cpufreq_hw_get(unsigned int cpu) ++{ ++ struct qcom_cpufreq_data *data; ++ struct cpufreq_policy *policy; ++ ++ policy = cpufreq_cpu_get_raw(cpu); ++ if (!policy) ++ return 0; ++ ++ data = policy->driver_data; ++ ++ return qcom_lmh_get_throttle_freq(data) / HZ_PER_KHZ; ++} ++ ++/* Get the frequency requested by the cpufreq core for the CPU */ ++static unsigned int qcom_cpufreq_get_freq(unsigned int cpu) + { + struct qcom_cpufreq_data *data; + const struct qcom_cpufreq_soc_data *soc_data; +@@ -193,6 +221,7 @@ static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev, + } + } else if (ret != -ENODEV) { + dev_err(cpu_dev, "Invalid opp table in device tree\n"); ++ kfree(table); + return ret; + } else { + policy->fast_switch_possible = true; +@@ -286,18 +315,6 @@ static void qcom_get_related_cpus(int index, struct cpumask *m) + } + } + +-static unsigned long qcom_lmh_get_throttle_freq(struct qcom_cpufreq_data *data) +-{ +- unsigned int lval; +- +- if (data->soc_data->reg_current_vote) +- lval = readl_relaxed(data->base + data->soc_data->reg_current_vote) & 0x3ff; +- else +- lval = readl_relaxed(data->base + data->soc_data->reg_domain_state) & 0xff; +- +- return lval * xo_rate; +-} +- + static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data) + { + struct cpufreq_policy *policy = data->policy; +@@ -341,7 +358,7 @@ static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data) + * If h/w throttled frequency is higher than what cpufreq has requested + * for, then stop polling and switch back to interrupt mechanism. + */ +- if (throttled_freq >= qcom_cpufreq_hw_get(cpu)) ++ if (throttled_freq >= qcom_cpufreq_get_freq(cpu)) + enable_irq(data->throttle_irq); + else + mod_delayed_work(system_highpri_wq, &data->throttle_work, +diff --git a/drivers/cpuidle/dt_idle_states.c b/drivers/cpuidle/dt_idle_states.c +index 252f2a9686a62..448bc796b0b40 100644 +--- a/drivers/cpuidle/dt_idle_states.c ++++ b/drivers/cpuidle/dt_idle_states.c +@@ -223,6 +223,6 @@ int dt_init_idle_driver(struct cpuidle_driver *drv, + * also be 0 on platforms with missing DT idle states or legacy DT + * configuration predating the DT idle states bindings. + */ +- return i; ++ return state_idx - start_idx; + } + EXPORT_SYMBOL_GPL(dt_init_idle_driver); +diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig +index 55e75fbb658ee..c30b5a39c2ac2 100644 +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -669,7 +669,12 @@ config CRYPTO_DEV_IMGTEC_HASH + config CRYPTO_DEV_ROCKCHIP + tristate "Rockchip's Cryptographic Engine driver" + depends on OF && ARCH_ROCKCHIP ++ depends on PM ++ select CRYPTO_ECB ++ select CRYPTO_CBC ++ select CRYPTO_DES + select CRYPTO_AES ++ select CRYPTO_ENGINE + select CRYPTO_LIB_DES + select CRYPTO_MD5 + select CRYPTO_SHA1 +diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c +index 910d6751644cf..902f6be057ec6 100644 +--- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c ++++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c +@@ -124,7 +124,7 @@ static int sun8i_ss_setup_ivs(struct skcipher_request *areq) + unsigned int ivsize = crypto_skcipher_ivsize(tfm); + struct sun8i_ss_flow *sf = &ss->flows[rctx->flow]; + int i = 0; +- u32 a; ++ dma_addr_t a; + int err; + + rctx->ivlen = ivsize; +diff --git a/drivers/crypto/amlogic/amlogic-gxl-core.c b/drivers/crypto/amlogic/amlogic-gxl-core.c +index 6e7ae896717cd..937187027ad57 100644 +--- a/drivers/crypto/amlogic/amlogic-gxl-core.c ++++ b/drivers/crypto/amlogic/amlogic-gxl-core.c +@@ -237,7 +237,6 @@ static int meson_crypto_probe(struct platform_device *pdev) + return err; + } + +- mc->irqs = devm_kcalloc(mc->dev, MAXFLOW, sizeof(int), GFP_KERNEL); + for (i = 0; i < MAXFLOW; i++) { + mc->irqs[i] = platform_get_irq(pdev, i); + if (mc->irqs[i] < 0) +diff --git a/drivers/crypto/amlogic/amlogic-gxl.h b/drivers/crypto/amlogic/amlogic-gxl.h +index dc0f142324a3c..8c0746a1d6d43 100644 +--- a/drivers/crypto/amlogic/amlogic-gxl.h ++++ b/drivers/crypto/amlogic/amlogic-gxl.h +@@ -95,7 +95,7 @@ struct meson_dev { + struct device *dev; + struct meson_flow *chanlist; + atomic_t flow; +- int *irqs; ++ int irqs[MAXFLOW]; + #ifdef CONFIG_CRYPTO_DEV_AMLOGIC_GXL_DEBUG + struct dentry *dbgfs_dir; + #endif +diff --git a/drivers/crypto/cavium/nitrox/nitrox_mbx.c b/drivers/crypto/cavium/nitrox/nitrox_mbx.c +index 9e7308e39b304..d4e06999af9b7 100644 +--- a/drivers/crypto/cavium/nitrox/nitrox_mbx.c ++++ b/drivers/crypto/cavium/nitrox/nitrox_mbx.c +@@ -195,6 +195,7 @@ int nitrox_mbox_init(struct nitrox_device *ndev) + ndev->iov.pf2vf_wq = alloc_workqueue("nitrox_pf2vf", 0, 0); + if (!ndev->iov.pf2vf_wq) { + kfree(ndev->iov.vfdev); ++ ndev->iov.vfdev = NULL; + return -ENOMEM; + } + /* enable pf2vf mailbox interrupts */ +diff --git a/drivers/crypto/ccree/cc_debugfs.c b/drivers/crypto/ccree/cc_debugfs.c +index 7083767602fcf..8f008f024f8f1 100644 +--- a/drivers/crypto/ccree/cc_debugfs.c ++++ b/drivers/crypto/ccree/cc_debugfs.c +@@ -55,7 +55,7 @@ void __init cc_debugfs_global_init(void) + cc_debugfs_dir = debugfs_create_dir("ccree", NULL); + } + +-void __exit cc_debugfs_global_fini(void) ++void cc_debugfs_global_fini(void) + { + debugfs_remove(cc_debugfs_dir); + } +diff --git a/drivers/crypto/ccree/cc_driver.c b/drivers/crypto/ccree/cc_driver.c +index cadead18b59e8..d489c6f808925 100644 +--- a/drivers/crypto/ccree/cc_driver.c ++++ b/drivers/crypto/ccree/cc_driver.c +@@ -651,9 +651,17 @@ static struct platform_driver ccree_driver = { + + static int __init ccree_init(void) + { ++ int rc; ++ + cc_debugfs_global_init(); + +- return platform_driver_register(&ccree_driver); ++ rc = platform_driver_register(&ccree_driver); ++ if (rc) { ++ cc_debugfs_global_fini(); ++ return rc; ++ } ++ ++ return 0; + } + module_init(ccree_init); + +diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c +index 471e5ca720f57..baf1faec7046f 100644 +--- a/drivers/crypto/hisilicon/hpre/hpre_main.c ++++ b/drivers/crypto/hisilicon/hpre/hpre_main.c +@@ -1437,18 +1437,12 @@ err_with_qm_init: + static void hpre_remove(struct pci_dev *pdev) + { + struct hisi_qm *qm = pci_get_drvdata(pdev); +- int ret; + + hisi_qm_pm_uninit(qm); + hisi_qm_wait_task_finish(qm, &hpre_devices); + hisi_qm_alg_unregister(qm, &hpre_devices); +- if (qm->fun_type == QM_HW_PF && qm->vfs_num) { +- ret = hisi_qm_sriov_disable(pdev, true); +- if (ret) { +- pci_err(pdev, "Disable SRIOV fail!\n"); +- return; +- } +- } ++ if (qm->fun_type == QM_HW_PF && qm->vfs_num) ++ hisi_qm_sriov_disable(pdev, true); + + hpre_debugfs_exit(qm); + hisi_qm_stop(qm, QM_NORMAL); +diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c +index 8b387de69d229..07e1e39a5e378 100644 +--- a/drivers/crypto/hisilicon/qm.c ++++ b/drivers/crypto/hisilicon/qm.c +@@ -250,7 +250,6 @@ + #define QM_QOS_MIN_CIR_B 100 + #define QM_QOS_MAX_CIR_U 6 + #define QM_QOS_MAX_CIR_S 11 +-#define QM_QOS_VAL_MAX_LEN 32 + #define QM_DFX_BASE 0x0100000 + #define QM_DFX_STATE1 0x0104000 + #define QM_DFX_STATE2 0x01040C8 +@@ -359,7 +358,7 @@ static const struct hisi_qm_cap_info qm_cap_info_vf[] = { + static const struct hisi_qm_cap_info qm_basic_info[] = { + {QM_TOTAL_QP_NUM_CAP, 0x100158, 0, GENMASK(10, 0), 0x1000, 0x400, 0x400}, + {QM_FUNC_MAX_QP_CAP, 0x100158, 11, GENMASK(10, 0), 0x1000, 0x400, 0x400}, +- {QM_XEQ_DEPTH_CAP, 0x3104, 0, GENMASK(15, 0), 0x800, 0x4000800, 0x4000800}, ++ {QM_XEQ_DEPTH_CAP, 0x3104, 0, GENMASK(31, 0), 0x800, 0x4000800, 0x4000800}, + {QM_QP_DEPTH_CAP, 0x3108, 0, GENMASK(31, 0), 0x4000400, 0x4000400, 0x4000400}, + {QM_EQ_IRQ_TYPE_CAP, 0x310c, 0, GENMASK(31, 0), 0x10000, 0x10000, 0x10000}, + {QM_AEQ_IRQ_TYPE_CAP, 0x3110, 0, GENMASK(31, 0), 0x0, 0x10001, 0x10001}, +@@ -909,8 +908,8 @@ static void qm_get_xqc_depth(struct hisi_qm *qm, u16 *low_bits, + u32 depth; + + depth = hisi_qm_get_hw_info(qm, qm_basic_info, type, qm->cap_ver); +- *high_bits = depth & QM_XQ_DEPTH_MASK; +- *low_bits = (depth >> QM_XQ_DEPTH_SHIFT) & QM_XQ_DEPTH_MASK; ++ *low_bits = depth & QM_XQ_DEPTH_MASK; ++ *high_bits = (depth >> QM_XQ_DEPTH_SHIFT) & QM_XQ_DEPTH_MASK; + } + + static u32 qm_get_irq_num(struct hisi_qm *qm) +@@ -4614,7 +4613,7 @@ static ssize_t qm_get_qos_value(struct hisi_qm *qm, const char *buf, + unsigned int *fun_index) + { + char tbuf_bdf[QM_DBG_READ_LEN] = {0}; +- char val_buf[QM_QOS_VAL_MAX_LEN] = {0}; ++ char val_buf[QM_DBG_READ_LEN] = {0}; + u32 tmp1, device, function; + int ret, bus; + +@@ -5725,6 +5724,7 @@ static void qm_pf_reset_vf_done(struct hisi_qm *qm) + cmd = QM_VF_START_FAIL; + } + ++ qm_cmd_init(qm); + ret = qm_ping_pf(qm, cmd); + if (ret) + dev_warn(&pdev->dev, "PF responds timeout in reset done!\n"); +@@ -5786,7 +5786,6 @@ static void qm_pf_reset_vf_process(struct hisi_qm *qm, + goto err_get_status; + + qm_pf_reset_vf_done(qm); +- qm_cmd_init(qm); + + dev_info(dev, "device reset done.\n"); + +diff --git a/drivers/crypto/img-hash.c b/drivers/crypto/img-hash.c +index d8e82d69745d8..9629e98bd68b7 100644 +--- a/drivers/crypto/img-hash.c ++++ b/drivers/crypto/img-hash.c +@@ -358,12 +358,16 @@ static int img_hash_dma_init(struct img_hash_dev *hdev) + static void img_hash_dma_task(unsigned long d) + { + struct img_hash_dev *hdev = (struct img_hash_dev *)d; +- struct img_hash_request_ctx *ctx = ahash_request_ctx(hdev->req); ++ struct img_hash_request_ctx *ctx; + u8 *addr; + size_t nbytes, bleft, wsend, len, tbc; + struct scatterlist tsg; + +- if (!hdev->req || !ctx->sg) ++ if (!hdev->req) ++ return; ++ ++ ctx = ahash_request_ctx(hdev->req); ++ if (!ctx->sg) + return; + + addr = sg_virt(ctx->sg); +diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c +index 655a7f5a406a1..cbeda59c6b191 100644 +--- a/drivers/crypto/omap-sham.c ++++ b/drivers/crypto/omap-sham.c +@@ -2114,7 +2114,7 @@ static int omap_sham_probe(struct platform_device *pdev) + + pm_runtime_enable(dev); + +- err = pm_runtime_get_sync(dev); ++ err = pm_runtime_resume_and_get(dev); + if (err < 0) { + dev_err(dev, "failed to get sync: %d\n", err); + goto err_pm; +diff --git a/drivers/crypto/qat/qat_4xxx/adf_drv.c b/drivers/crypto/qat/qat_4xxx/adf_drv.c +index 2f212561acc47..670a58b25cb16 100644 +--- a/drivers/crypto/qat/qat_4xxx/adf_drv.c ++++ b/drivers/crypto/qat/qat_4xxx/adf_drv.c +@@ -261,6 +261,7 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + hw_data->accel_capabilities_mask = hw_data->get_accel_cap(accel_dev); + if (!hw_data->accel_capabilities_mask) { + dev_err(&pdev->dev, "Failed to get capabilities mask.\n"); ++ ret = -EINVAL; + goto out_err; + } + +diff --git a/drivers/crypto/rockchip/rk3288_crypto.c b/drivers/crypto/rockchip/rk3288_crypto.c +index 35d73061d1569..14a0aef18ab13 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto.c ++++ b/drivers/crypto/rockchip/rk3288_crypto.c +@@ -65,186 +65,24 @@ static void rk_crypto_disable_clk(struct rk_crypto_info *dev) + clk_disable_unprepare(dev->sclk); + } + +-static int check_alignment(struct scatterlist *sg_src, +- struct scatterlist *sg_dst, +- int align_mask) +-{ +- int in, out, align; +- +- in = IS_ALIGNED((uint32_t)sg_src->offset, 4) && +- IS_ALIGNED((uint32_t)sg_src->length, align_mask); +- if (!sg_dst) +- return in; +- out = IS_ALIGNED((uint32_t)sg_dst->offset, 4) && +- IS_ALIGNED((uint32_t)sg_dst->length, align_mask); +- align = in && out; +- +- return (align && (sg_src->length == sg_dst->length)); +-} +- +-static int rk_load_data(struct rk_crypto_info *dev, +- struct scatterlist *sg_src, +- struct scatterlist *sg_dst) +-{ +- unsigned int count; +- +- dev->aligned = dev->aligned ? +- check_alignment(sg_src, sg_dst, dev->align_size) : +- dev->aligned; +- if (dev->aligned) { +- count = min(dev->left_bytes, sg_src->length); +- dev->left_bytes -= count; +- +- if (!dma_map_sg(dev->dev, sg_src, 1, DMA_TO_DEVICE)) { +- dev_err(dev->dev, "[%s:%d] dma_map_sg(src) error\n", +- __func__, __LINE__); +- return -EINVAL; +- } +- dev->addr_in = sg_dma_address(sg_src); +- +- if (sg_dst) { +- if (!dma_map_sg(dev->dev, sg_dst, 1, DMA_FROM_DEVICE)) { +- dev_err(dev->dev, +- "[%s:%d] dma_map_sg(dst) error\n", +- __func__, __LINE__); +- dma_unmap_sg(dev->dev, sg_src, 1, +- DMA_TO_DEVICE); +- return -EINVAL; +- } +- dev->addr_out = sg_dma_address(sg_dst); +- } +- } else { +- count = (dev->left_bytes > PAGE_SIZE) ? +- PAGE_SIZE : dev->left_bytes; +- +- if (!sg_pcopy_to_buffer(dev->first, dev->src_nents, +- dev->addr_vir, count, +- dev->total - dev->left_bytes)) { +- dev_err(dev->dev, "[%s:%d] pcopy err\n", +- __func__, __LINE__); +- return -EINVAL; +- } +- dev->left_bytes -= count; +- sg_init_one(&dev->sg_tmp, dev->addr_vir, count); +- if (!dma_map_sg(dev->dev, &dev->sg_tmp, 1, DMA_TO_DEVICE)) { +- dev_err(dev->dev, "[%s:%d] dma_map_sg(sg_tmp) error\n", +- __func__, __LINE__); +- return -ENOMEM; +- } +- dev->addr_in = sg_dma_address(&dev->sg_tmp); +- +- if (sg_dst) { +- if (!dma_map_sg(dev->dev, &dev->sg_tmp, 1, +- DMA_FROM_DEVICE)) { +- dev_err(dev->dev, +- "[%s:%d] dma_map_sg(sg_tmp) error\n", +- __func__, __LINE__); +- dma_unmap_sg(dev->dev, &dev->sg_tmp, 1, +- DMA_TO_DEVICE); +- return -ENOMEM; +- } +- dev->addr_out = sg_dma_address(&dev->sg_tmp); +- } +- } +- dev->count = count; +- return 0; +-} +- +-static void rk_unload_data(struct rk_crypto_info *dev) +-{ +- struct scatterlist *sg_in, *sg_out; +- +- sg_in = dev->aligned ? dev->sg_src : &dev->sg_tmp; +- dma_unmap_sg(dev->dev, sg_in, 1, DMA_TO_DEVICE); +- +- if (dev->sg_dst) { +- sg_out = dev->aligned ? dev->sg_dst : &dev->sg_tmp; +- dma_unmap_sg(dev->dev, sg_out, 1, DMA_FROM_DEVICE); +- } +-} +- + static irqreturn_t rk_crypto_irq_handle(int irq, void *dev_id) + { + struct rk_crypto_info *dev = platform_get_drvdata(dev_id); + u32 interrupt_status; + +- spin_lock(&dev->lock); + interrupt_status = CRYPTO_READ(dev, RK_CRYPTO_INTSTS); + CRYPTO_WRITE(dev, RK_CRYPTO_INTSTS, interrupt_status); + ++ dev->status = 1; + if (interrupt_status & 0x0a) { + dev_warn(dev->dev, "DMA Error\n"); +- dev->err = -EFAULT; ++ dev->status = 0; + } +- tasklet_schedule(&dev->done_task); ++ complete(&dev->complete); + +- spin_unlock(&dev->lock); + return IRQ_HANDLED; + } + +-static int rk_crypto_enqueue(struct rk_crypto_info *dev, +- struct crypto_async_request *async_req) +-{ +- unsigned long flags; +- int ret; +- +- spin_lock_irqsave(&dev->lock, flags); +- ret = crypto_enqueue_request(&dev->queue, async_req); +- if (dev->busy) { +- spin_unlock_irqrestore(&dev->lock, flags); +- return ret; +- } +- dev->busy = true; +- spin_unlock_irqrestore(&dev->lock, flags); +- tasklet_schedule(&dev->queue_task); +- +- return ret; +-} +- +-static void rk_crypto_queue_task_cb(unsigned long data) +-{ +- struct rk_crypto_info *dev = (struct rk_crypto_info *)data; +- struct crypto_async_request *async_req, *backlog; +- unsigned long flags; +- int err = 0; +- +- dev->err = 0; +- spin_lock_irqsave(&dev->lock, flags); +- backlog = crypto_get_backlog(&dev->queue); +- async_req = crypto_dequeue_request(&dev->queue); +- +- if (!async_req) { +- dev->busy = false; +- spin_unlock_irqrestore(&dev->lock, flags); +- return; +- } +- spin_unlock_irqrestore(&dev->lock, flags); +- +- if (backlog) { +- backlog->complete(backlog, -EINPROGRESS); +- backlog = NULL; +- } +- +- dev->async_req = async_req; +- err = dev->start(dev); +- if (err) +- dev->complete(dev->async_req, err); +-} +- +-static void rk_crypto_done_task_cb(unsigned long data) +-{ +- struct rk_crypto_info *dev = (struct rk_crypto_info *)data; +- +- if (dev->err) { +- dev->complete(dev->async_req, dev->err); +- return; +- } +- +- dev->err = dev->update(dev); +- if (dev->err) +- dev->complete(dev->async_req, dev->err); +-} +- + static struct rk_crypto_tmp *rk_cipher_algs[] = { + &rk_ecb_aes_alg, + &rk_cbc_aes_alg, +@@ -337,8 +175,6 @@ static int rk_crypto_probe(struct platform_device *pdev) + if (err) + goto err_crypto; + +- spin_lock_init(&crypto_info->lock); +- + crypto_info->reg = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(crypto_info->reg)) { + err = PTR_ERR(crypto_info->reg); +@@ -389,18 +225,11 @@ static int rk_crypto_probe(struct platform_device *pdev) + crypto_info->dev = &pdev->dev; + platform_set_drvdata(pdev, crypto_info); + +- tasklet_init(&crypto_info->queue_task, +- rk_crypto_queue_task_cb, (unsigned long)crypto_info); +- tasklet_init(&crypto_info->done_task, +- rk_crypto_done_task_cb, (unsigned long)crypto_info); +- crypto_init_queue(&crypto_info->queue, 50); ++ crypto_info->engine = crypto_engine_alloc_init(&pdev->dev, true); ++ crypto_engine_start(crypto_info->engine); ++ init_completion(&crypto_info->complete); + +- crypto_info->enable_clk = rk_crypto_enable_clk; +- crypto_info->disable_clk = rk_crypto_disable_clk; +- crypto_info->load_data = rk_load_data; +- crypto_info->unload_data = rk_unload_data; +- crypto_info->enqueue = rk_crypto_enqueue; +- crypto_info->busy = false; ++ rk_crypto_enable_clk(crypto_info); + + err = rk_crypto_register(crypto_info); + if (err) { +@@ -412,9 +241,9 @@ static int rk_crypto_probe(struct platform_device *pdev) + return 0; + + err_register_alg: +- tasklet_kill(&crypto_info->queue_task); +- tasklet_kill(&crypto_info->done_task); ++ crypto_engine_exit(crypto_info->engine); + err_crypto: ++ dev_err(dev, "Crypto Accelerator not successfully registered\n"); + return err; + } + +@@ -423,8 +252,8 @@ static int rk_crypto_remove(struct platform_device *pdev) + struct rk_crypto_info *crypto_tmp = platform_get_drvdata(pdev); + + rk_crypto_unregister(); +- tasklet_kill(&crypto_tmp->done_task); +- tasklet_kill(&crypto_tmp->queue_task); ++ rk_crypto_disable_clk(crypto_tmp); ++ crypto_engine_exit(crypto_tmp->engine); + return 0; + } + +diff --git a/drivers/crypto/rockchip/rk3288_crypto.h b/drivers/crypto/rockchip/rk3288_crypto.h +index 97278c2574ff9..045e811b4af84 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto.h ++++ b/drivers/crypto/rockchip/rk3288_crypto.h +@@ -5,9 +5,11 @@ + #include <crypto/aes.h> + #include <crypto/internal/des.h> + #include <crypto/algapi.h> ++#include <linux/dma-mapping.h> + #include <linux/interrupt.h> + #include <linux/delay.h> + #include <linux/scatterlist.h> ++#include <crypto/engine.h> + #include <crypto/internal/hash.h> + #include <crypto/internal/skcipher.h> + +@@ -193,45 +195,15 @@ struct rk_crypto_info { + struct reset_control *rst; + void __iomem *reg; + int irq; +- struct crypto_queue queue; +- struct tasklet_struct queue_task; +- struct tasklet_struct done_task; +- struct crypto_async_request *async_req; +- int err; +- /* device lock */ +- spinlock_t lock; +- +- /* the public variable */ +- struct scatterlist *sg_src; +- struct scatterlist *sg_dst; +- struct scatterlist sg_tmp; +- struct scatterlist *first; +- unsigned int left_bytes; +- void *addr_vir; +- int aligned; +- int align_size; +- size_t src_nents; +- size_t dst_nents; +- unsigned int total; +- unsigned int count; +- dma_addr_t addr_in; +- dma_addr_t addr_out; +- bool busy; +- int (*start)(struct rk_crypto_info *dev); +- int (*update)(struct rk_crypto_info *dev); +- void (*complete)(struct crypto_async_request *base, int err); +- int (*enable_clk)(struct rk_crypto_info *dev); +- void (*disable_clk)(struct rk_crypto_info *dev); +- int (*load_data)(struct rk_crypto_info *dev, +- struct scatterlist *sg_src, +- struct scatterlist *sg_dst); +- void (*unload_data)(struct rk_crypto_info *dev); +- int (*enqueue)(struct rk_crypto_info *dev, +- struct crypto_async_request *async_req); ++ ++ struct crypto_engine *engine; ++ struct completion complete; ++ int status; + }; + + /* the private variable of hash */ + struct rk_ahash_ctx { ++ struct crypto_engine_ctx enginectx; + struct rk_crypto_info *dev; + /* for fallback */ + struct crypto_ahash *fallback_tfm; +@@ -241,14 +213,23 @@ struct rk_ahash_ctx { + struct rk_ahash_rctx { + struct ahash_request fallback_req; + u32 mode; ++ int nrsg; + }; + + /* the private variable of cipher */ + struct rk_cipher_ctx { ++ struct crypto_engine_ctx enginectx; + struct rk_crypto_info *dev; + unsigned int keylen; +- u32 mode; ++ u8 key[AES_MAX_KEY_SIZE]; + u8 iv[AES_BLOCK_SIZE]; ++ struct crypto_skcipher *fallback_tfm; ++}; ++ ++struct rk_cipher_rctx { ++ u8 backup_iv[AES_BLOCK_SIZE]; ++ u32 mode; ++ struct skcipher_request fallback_req; // keep at the end + }; + + enum alg_type { +diff --git a/drivers/crypto/rockchip/rk3288_crypto_ahash.c b/drivers/crypto/rockchip/rk3288_crypto_ahash.c +index ed03058497bc2..edd40e16a3f0a 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto_ahash.c ++++ b/drivers/crypto/rockchip/rk3288_crypto_ahash.c +@@ -9,6 +9,7 @@ + * Some ideas are from marvell/cesa.c and s5p-sss.c driver. + */ + #include <linux/device.h> ++#include <asm/unaligned.h> + #include "rk3288_crypto.h" + + /* +@@ -16,6 +17,40 @@ + * so we put the fixed hash out when met zero message. + */ + ++static bool rk_ahash_need_fallback(struct ahash_request *req) ++{ ++ struct scatterlist *sg; ++ ++ sg = req->src; ++ while (sg) { ++ if (!IS_ALIGNED(sg->offset, sizeof(u32))) { ++ return true; ++ } ++ if (sg->length % 4) { ++ return true; ++ } ++ sg = sg_next(sg); ++ } ++ return false; ++} ++ ++static int rk_ahash_digest_fb(struct ahash_request *areq) ++{ ++ struct rk_ahash_rctx *rctx = ahash_request_ctx(areq); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); ++ struct rk_ahash_ctx *tfmctx = crypto_ahash_ctx(tfm); ++ ++ ahash_request_set_tfm(&rctx->fallback_req, tfmctx->fallback_tfm); ++ rctx->fallback_req.base.flags = areq->base.flags & ++ CRYPTO_TFM_REQ_MAY_SLEEP; ++ ++ rctx->fallback_req.nbytes = areq->nbytes; ++ rctx->fallback_req.src = areq->src; ++ rctx->fallback_req.result = areq->result; ++ ++ return crypto_ahash_digest(&rctx->fallback_req); ++} ++ + static int zero_message_process(struct ahash_request *req) + { + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); +@@ -38,16 +73,12 @@ static int zero_message_process(struct ahash_request *req) + return 0; + } + +-static void rk_ahash_crypto_complete(struct crypto_async_request *base, int err) +-{ +- if (base->complete) +- base->complete(base, err); +-} +- +-static void rk_ahash_reg_init(struct rk_crypto_info *dev) ++static void rk_ahash_reg_init(struct ahash_request *req) + { +- struct ahash_request *req = ahash_request_cast(dev->async_req); + struct rk_ahash_rctx *rctx = ahash_request_ctx(req); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ struct rk_ahash_ctx *tctx = crypto_ahash_ctx(tfm); ++ struct rk_crypto_info *dev = tctx->dev; + int reg_status; + + reg_status = CRYPTO_READ(dev, RK_CRYPTO_CTRL) | +@@ -74,7 +105,7 @@ static void rk_ahash_reg_init(struct rk_crypto_info *dev) + RK_CRYPTO_BYTESWAP_BRFIFO | + RK_CRYPTO_BYTESWAP_BTFIFO); + +- CRYPTO_WRITE(dev, RK_CRYPTO_HASH_MSG_LEN, dev->total); ++ CRYPTO_WRITE(dev, RK_CRYPTO_HASH_MSG_LEN, req->nbytes); + } + + static int rk_ahash_init(struct ahash_request *req) +@@ -167,48 +198,64 @@ static int rk_ahash_digest(struct ahash_request *req) + struct rk_ahash_ctx *tctx = crypto_tfm_ctx(req->base.tfm); + struct rk_crypto_info *dev = tctx->dev; + ++ if (rk_ahash_need_fallback(req)) ++ return rk_ahash_digest_fb(req); ++ + if (!req->nbytes) + return zero_message_process(req); +- else +- return dev->enqueue(dev, &req->base); ++ ++ return crypto_transfer_hash_request_to_engine(dev->engine, req); + } + +-static void crypto_ahash_dma_start(struct rk_crypto_info *dev) ++static void crypto_ahash_dma_start(struct rk_crypto_info *dev, struct scatterlist *sg) + { +- CRYPTO_WRITE(dev, RK_CRYPTO_HRDMAS, dev->addr_in); +- CRYPTO_WRITE(dev, RK_CRYPTO_HRDMAL, (dev->count + 3) / 4); ++ CRYPTO_WRITE(dev, RK_CRYPTO_HRDMAS, sg_dma_address(sg)); ++ CRYPTO_WRITE(dev, RK_CRYPTO_HRDMAL, sg_dma_len(sg) / 4); + CRYPTO_WRITE(dev, RK_CRYPTO_CTRL, RK_CRYPTO_HASH_START | + (RK_CRYPTO_HASH_START << 16)); + } + +-static int rk_ahash_set_data_start(struct rk_crypto_info *dev) ++static int rk_hash_prepare(struct crypto_engine *engine, void *breq) ++{ ++ struct ahash_request *areq = container_of(breq, struct ahash_request, base); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); ++ struct rk_ahash_rctx *rctx = ahash_request_ctx(areq); ++ struct rk_ahash_ctx *tctx = crypto_ahash_ctx(tfm); ++ int ret; ++ ++ ret = dma_map_sg(tctx->dev->dev, areq->src, sg_nents(areq->src), DMA_TO_DEVICE); ++ if (ret <= 0) ++ return -EINVAL; ++ ++ rctx->nrsg = ret; ++ ++ return 0; ++} ++ ++static int rk_hash_unprepare(struct crypto_engine *engine, void *breq) + { +- int err; ++ struct ahash_request *areq = container_of(breq, struct ahash_request, base); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); ++ struct rk_ahash_rctx *rctx = ahash_request_ctx(areq); ++ struct rk_ahash_ctx *tctx = crypto_ahash_ctx(tfm); + +- err = dev->load_data(dev, dev->sg_src, NULL); +- if (!err) +- crypto_ahash_dma_start(dev); +- return err; ++ dma_unmap_sg(tctx->dev->dev, areq->src, rctx->nrsg, DMA_TO_DEVICE); ++ return 0; + } + +-static int rk_ahash_start(struct rk_crypto_info *dev) ++static int rk_hash_run(struct crypto_engine *engine, void *breq) + { +- struct ahash_request *req = ahash_request_cast(dev->async_req); +- struct crypto_ahash *tfm; +- struct rk_ahash_rctx *rctx; +- +- dev->total = req->nbytes; +- dev->left_bytes = req->nbytes; +- dev->aligned = 0; +- dev->align_size = 4; +- dev->sg_dst = NULL; +- dev->sg_src = req->src; +- dev->first = req->src; +- dev->src_nents = sg_nents(req->src); +- rctx = ahash_request_ctx(req); ++ struct ahash_request *areq = container_of(breq, struct ahash_request, base); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); ++ struct rk_ahash_rctx *rctx = ahash_request_ctx(areq); ++ struct rk_ahash_ctx *tctx = crypto_ahash_ctx(tfm); ++ struct scatterlist *sg = areq->src; ++ int err = 0; ++ int i; ++ u32 v; ++ + rctx->mode = 0; + +- tfm = crypto_ahash_reqtfm(req); + switch (crypto_ahash_digestsize(tfm)) { + case SHA1_DIGEST_SIZE: + rctx->mode = RK_CRYPTO_HASH_SHA1; +@@ -220,32 +267,26 @@ static int rk_ahash_start(struct rk_crypto_info *dev) + rctx->mode = RK_CRYPTO_HASH_MD5; + break; + default: +- return -EINVAL; ++ err = -EINVAL; ++ goto theend; + } + +- rk_ahash_reg_init(dev); +- return rk_ahash_set_data_start(dev); +-} +- +-static int rk_ahash_crypto_rx(struct rk_crypto_info *dev) +-{ +- int err = 0; +- struct ahash_request *req = ahash_request_cast(dev->async_req); +- struct crypto_ahash *tfm; +- +- dev->unload_data(dev); +- if (dev->left_bytes) { +- if (dev->aligned) { +- if (sg_is_last(dev->sg_src)) { +- dev_warn(dev->dev, "[%s:%d], Lack of data\n", +- __func__, __LINE__); +- err = -ENOMEM; +- goto out_rx; +- } +- dev->sg_src = sg_next(dev->sg_src); ++ rk_ahash_reg_init(areq); ++ ++ while (sg) { ++ reinit_completion(&tctx->dev->complete); ++ tctx->dev->status = 0; ++ crypto_ahash_dma_start(tctx->dev, sg); ++ wait_for_completion_interruptible_timeout(&tctx->dev->complete, ++ msecs_to_jiffies(2000)); ++ if (!tctx->dev->status) { ++ dev_err(tctx->dev->dev, "DMA timeout\n"); ++ err = -EFAULT; ++ goto theend; + } +- err = rk_ahash_set_data_start(dev); +- } else { ++ sg = sg_next(sg); ++ } ++ + /* + * it will take some time to process date after last dma + * transmission. +@@ -256,18 +297,20 @@ static int rk_ahash_crypto_rx(struct rk_crypto_info *dev) + * efficiency, and make it response quickly when dma + * complete. + */ +- while (!CRYPTO_READ(dev, RK_CRYPTO_HASH_STS)) +- udelay(10); +- +- tfm = crypto_ahash_reqtfm(req); +- memcpy_fromio(req->result, dev->reg + RK_CRYPTO_HASH_DOUT_0, +- crypto_ahash_digestsize(tfm)); +- dev->complete(dev->async_req, 0); +- tasklet_schedule(&dev->queue_task); ++ while (!CRYPTO_READ(tctx->dev, RK_CRYPTO_HASH_STS)) ++ udelay(10); ++ ++ for (i = 0; i < crypto_ahash_digestsize(tfm) / 4; i++) { ++ v = readl(tctx->dev->reg + RK_CRYPTO_HASH_DOUT_0 + i * 4); ++ put_unaligned_le32(v, areq->result + i * 4); + } + +-out_rx: +- return err; ++theend: ++ local_bh_disable(); ++ crypto_finalize_hash_request(engine, breq, err); ++ local_bh_enable(); ++ ++ return 0; + } + + static int rk_cra_hash_init(struct crypto_tfm *tfm) +@@ -281,14 +324,6 @@ static int rk_cra_hash_init(struct crypto_tfm *tfm) + algt = container_of(alg, struct rk_crypto_tmp, alg.hash); + + tctx->dev = algt->dev; +- tctx->dev->addr_vir = (void *)__get_free_page(GFP_KERNEL); +- if (!tctx->dev->addr_vir) { +- dev_err(tctx->dev->dev, "failed to kmalloc for addr_vir\n"); +- return -ENOMEM; +- } +- tctx->dev->start = rk_ahash_start; +- tctx->dev->update = rk_ahash_crypto_rx; +- tctx->dev->complete = rk_ahash_crypto_complete; + + /* for fallback */ + tctx->fallback_tfm = crypto_alloc_ahash(alg_name, 0, +@@ -297,19 +332,23 @@ static int rk_cra_hash_init(struct crypto_tfm *tfm) + dev_err(tctx->dev->dev, "Could not load fallback driver.\n"); + return PTR_ERR(tctx->fallback_tfm); + } ++ + crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), + sizeof(struct rk_ahash_rctx) + + crypto_ahash_reqsize(tctx->fallback_tfm)); + +- return tctx->dev->enable_clk(tctx->dev); ++ tctx->enginectx.op.do_one_request = rk_hash_run; ++ tctx->enginectx.op.prepare_request = rk_hash_prepare; ++ tctx->enginectx.op.unprepare_request = rk_hash_unprepare; ++ ++ return 0; + } + + static void rk_cra_hash_exit(struct crypto_tfm *tfm) + { + struct rk_ahash_ctx *tctx = crypto_tfm_ctx(tfm); + +- free_page((unsigned long)tctx->dev->addr_vir); +- return tctx->dev->disable_clk(tctx->dev); ++ crypto_free_ahash(tctx->fallback_tfm); + } + + struct rk_crypto_tmp rk_ahash_sha1 = { +diff --git a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c +index 5bbf0d2722e11..67a7e05d5ae31 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c ++++ b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c +@@ -9,23 +9,77 @@ + * Some ideas are from marvell-cesa.c and s5p-sss.c driver. + */ + #include <linux/device.h> ++#include <crypto/scatterwalk.h> + #include "rk3288_crypto.h" + + #define RK_CRYPTO_DEC BIT(0) + +-static void rk_crypto_complete(struct crypto_async_request *base, int err) ++static int rk_cipher_need_fallback(struct skcipher_request *req) + { +- if (base->complete) +- base->complete(base, err); ++ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); ++ unsigned int bs = crypto_skcipher_blocksize(tfm); ++ struct scatterlist *sgs, *sgd; ++ unsigned int stodo, dtodo, len; ++ ++ if (!req->cryptlen) ++ return true; ++ ++ len = req->cryptlen; ++ sgs = req->src; ++ sgd = req->dst; ++ while (sgs && sgd) { ++ if (!IS_ALIGNED(sgs->offset, sizeof(u32))) { ++ return true; ++ } ++ if (!IS_ALIGNED(sgd->offset, sizeof(u32))) { ++ return true; ++ } ++ stodo = min(len, sgs->length); ++ if (stodo % bs) { ++ return true; ++ } ++ dtodo = min(len, sgd->length); ++ if (dtodo % bs) { ++ return true; ++ } ++ if (stodo != dtodo) { ++ return true; ++ } ++ len -= stodo; ++ sgs = sg_next(sgs); ++ sgd = sg_next(sgd); ++ } ++ return false; ++} ++ ++static int rk_cipher_fallback(struct skcipher_request *areq) ++{ ++ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); ++ struct rk_cipher_ctx *op = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(areq); ++ int err; ++ ++ skcipher_request_set_tfm(&rctx->fallback_req, op->fallback_tfm); ++ skcipher_request_set_callback(&rctx->fallback_req, areq->base.flags, ++ areq->base.complete, areq->base.data); ++ skcipher_request_set_crypt(&rctx->fallback_req, areq->src, areq->dst, ++ areq->cryptlen, areq->iv); ++ if (rctx->mode & RK_CRYPTO_DEC) ++ err = crypto_skcipher_decrypt(&rctx->fallback_req); ++ else ++ err = crypto_skcipher_encrypt(&rctx->fallback_req); ++ return err; + } + + static int rk_handle_req(struct rk_crypto_info *dev, + struct skcipher_request *req) + { +- if (!IS_ALIGNED(req->cryptlen, dev->align_size)) +- return -EINVAL; +- else +- return dev->enqueue(dev, &req->base); ++ struct crypto_engine *engine = dev->engine; ++ ++ if (rk_cipher_need_fallback(req)) ++ return rk_cipher_fallback(req); ++ ++ return crypto_transfer_skcipher_request_to_engine(engine, req); + } + + static int rk_aes_setkey(struct crypto_skcipher *cipher, +@@ -38,8 +92,9 @@ static int rk_aes_setkey(struct crypto_skcipher *cipher, + keylen != AES_KEYSIZE_256) + return -EINVAL; + ctx->keylen = keylen; +- memcpy_toio(ctx->dev->reg + RK_CRYPTO_AES_KEY_0, key, keylen); +- return 0; ++ memcpy(ctx->key, key, keylen); ++ ++ return crypto_skcipher_setkey(ctx->fallback_tfm, key, keylen); + } + + static int rk_des_setkey(struct crypto_skcipher *cipher, +@@ -53,8 +108,9 @@ static int rk_des_setkey(struct crypto_skcipher *cipher, + return err; + + ctx->keylen = keylen; +- memcpy_toio(ctx->dev->reg + RK_CRYPTO_TDES_KEY1_0, key, keylen); +- return 0; ++ memcpy(ctx->key, key, keylen); ++ ++ return crypto_skcipher_setkey(ctx->fallback_tfm, key, keylen); + } + + static int rk_tdes_setkey(struct crypto_skcipher *cipher, +@@ -68,17 +124,19 @@ static int rk_tdes_setkey(struct crypto_skcipher *cipher, + return err; + + ctx->keylen = keylen; +- memcpy_toio(ctx->dev->reg + RK_CRYPTO_TDES_KEY1_0, key, keylen); +- return 0; ++ memcpy(ctx->key, key, keylen); ++ ++ return crypto_skcipher_setkey(ctx->fallback_tfm, key, keylen); + } + + static int rk_aes_ecb_encrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_AES_ECB_MODE; ++ rctx->mode = RK_CRYPTO_AES_ECB_MODE; + return rk_handle_req(dev, req); + } + +@@ -86,9 +144,10 @@ static int rk_aes_ecb_decrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_AES_ECB_MODE | RK_CRYPTO_DEC; ++ rctx->mode = RK_CRYPTO_AES_ECB_MODE | RK_CRYPTO_DEC; + return rk_handle_req(dev, req); + } + +@@ -96,9 +155,10 @@ static int rk_aes_cbc_encrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_AES_CBC_MODE; ++ rctx->mode = RK_CRYPTO_AES_CBC_MODE; + return rk_handle_req(dev, req); + } + +@@ -106,9 +166,10 @@ static int rk_aes_cbc_decrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_AES_CBC_MODE | RK_CRYPTO_DEC; ++ rctx->mode = RK_CRYPTO_AES_CBC_MODE | RK_CRYPTO_DEC; + return rk_handle_req(dev, req); + } + +@@ -116,9 +177,10 @@ static int rk_des_ecb_encrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = 0; ++ rctx->mode = 0; + return rk_handle_req(dev, req); + } + +@@ -126,9 +188,10 @@ static int rk_des_ecb_decrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_DEC; ++ rctx->mode = RK_CRYPTO_DEC; + return rk_handle_req(dev, req); + } + +@@ -136,9 +199,10 @@ static int rk_des_cbc_encrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_TDES_CHAINMODE_CBC; ++ rctx->mode = RK_CRYPTO_TDES_CHAINMODE_CBC; + return rk_handle_req(dev, req); + } + +@@ -146,9 +210,10 @@ static int rk_des_cbc_decrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_TDES_CHAINMODE_CBC | RK_CRYPTO_DEC; ++ rctx->mode = RK_CRYPTO_TDES_CHAINMODE_CBC | RK_CRYPTO_DEC; + return rk_handle_req(dev, req); + } + +@@ -156,9 +221,10 @@ static int rk_des3_ede_ecb_encrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_TDES_SELECT; ++ rctx->mode = RK_CRYPTO_TDES_SELECT; + return rk_handle_req(dev, req); + } + +@@ -166,9 +232,10 @@ static int rk_des3_ede_ecb_decrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_DEC; ++ rctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_DEC; + return rk_handle_req(dev, req); + } + +@@ -176,9 +243,10 @@ static int rk_des3_ede_cbc_encrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_TDES_CHAINMODE_CBC; ++ rctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_TDES_CHAINMODE_CBC; + return rk_handle_req(dev, req); + } + +@@ -186,43 +254,42 @@ static int rk_des3_ede_cbc_decrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_TDES_CHAINMODE_CBC | ++ rctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_TDES_CHAINMODE_CBC | + RK_CRYPTO_DEC; + return rk_handle_req(dev, req); + } + +-static void rk_ablk_hw_init(struct rk_crypto_info *dev) ++static void rk_ablk_hw_init(struct rk_crypto_info *dev, struct skcipher_request *req) + { +- struct skcipher_request *req = +- skcipher_request_cast(dev->async_req); + struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req); + struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(cipher); +- u32 ivsize, block, conf_reg = 0; ++ u32 block, conf_reg = 0; + + block = crypto_tfm_alg_blocksize(tfm); +- ivsize = crypto_skcipher_ivsize(cipher); + + if (block == DES_BLOCK_SIZE) { +- ctx->mode |= RK_CRYPTO_TDES_FIFO_MODE | ++ rctx->mode |= RK_CRYPTO_TDES_FIFO_MODE | + RK_CRYPTO_TDES_BYTESWAP_KEY | + RK_CRYPTO_TDES_BYTESWAP_IV; +- CRYPTO_WRITE(dev, RK_CRYPTO_TDES_CTRL, ctx->mode); +- memcpy_toio(dev->reg + RK_CRYPTO_TDES_IV_0, req->iv, ivsize); ++ CRYPTO_WRITE(dev, RK_CRYPTO_TDES_CTRL, rctx->mode); ++ memcpy_toio(ctx->dev->reg + RK_CRYPTO_TDES_KEY1_0, ctx->key, ctx->keylen); + conf_reg = RK_CRYPTO_DESSEL; + } else { +- ctx->mode |= RK_CRYPTO_AES_FIFO_MODE | ++ rctx->mode |= RK_CRYPTO_AES_FIFO_MODE | + RK_CRYPTO_AES_KEY_CHANGE | + RK_CRYPTO_AES_BYTESWAP_KEY | + RK_CRYPTO_AES_BYTESWAP_IV; + if (ctx->keylen == AES_KEYSIZE_192) +- ctx->mode |= RK_CRYPTO_AES_192BIT_key; ++ rctx->mode |= RK_CRYPTO_AES_192BIT_key; + else if (ctx->keylen == AES_KEYSIZE_256) +- ctx->mode |= RK_CRYPTO_AES_256BIT_key; +- CRYPTO_WRITE(dev, RK_CRYPTO_AES_CTRL, ctx->mode); +- memcpy_toio(dev->reg + RK_CRYPTO_AES_IV_0, req->iv, ivsize); ++ rctx->mode |= RK_CRYPTO_AES_256BIT_key; ++ CRYPTO_WRITE(dev, RK_CRYPTO_AES_CTRL, rctx->mode); ++ memcpy_toio(ctx->dev->reg + RK_CRYPTO_AES_KEY_0, ctx->key, ctx->keylen); + } + conf_reg |= RK_CRYPTO_BYTESWAP_BTFIFO | + RK_CRYPTO_BYTESWAP_BRFIFO; +@@ -231,146 +298,138 @@ static void rk_ablk_hw_init(struct rk_crypto_info *dev) + RK_CRYPTO_BCDMA_ERR_ENA | RK_CRYPTO_BCDMA_DONE_ENA); + } + +-static void crypto_dma_start(struct rk_crypto_info *dev) ++static void crypto_dma_start(struct rk_crypto_info *dev, ++ struct scatterlist *sgs, ++ struct scatterlist *sgd, unsigned int todo) + { +- CRYPTO_WRITE(dev, RK_CRYPTO_BRDMAS, dev->addr_in); +- CRYPTO_WRITE(dev, RK_CRYPTO_BRDMAL, dev->count / 4); +- CRYPTO_WRITE(dev, RK_CRYPTO_BTDMAS, dev->addr_out); ++ CRYPTO_WRITE(dev, RK_CRYPTO_BRDMAS, sg_dma_address(sgs)); ++ CRYPTO_WRITE(dev, RK_CRYPTO_BRDMAL, todo); ++ CRYPTO_WRITE(dev, RK_CRYPTO_BTDMAS, sg_dma_address(sgd)); + CRYPTO_WRITE(dev, RK_CRYPTO_CTRL, RK_CRYPTO_BLOCK_START | + _SBF(RK_CRYPTO_BLOCK_START, 16)); + } + +-static int rk_set_data_start(struct rk_crypto_info *dev) ++static int rk_cipher_run(struct crypto_engine *engine, void *async_req) + { +- int err; +- struct skcipher_request *req = +- skcipher_request_cast(dev->async_req); +- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); ++ struct skcipher_request *areq = container_of(async_req, struct skcipher_request, base); ++ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); +- u32 ivsize = crypto_skcipher_ivsize(tfm); +- u8 *src_last_blk = page_address(sg_page(dev->sg_src)) + +- dev->sg_src->offset + dev->sg_src->length - ivsize; +- +- /* Store the iv that need to be updated in chain mode. +- * And update the IV buffer to contain the next IV for decryption mode. +- */ +- if (ctx->mode & RK_CRYPTO_DEC) { +- memcpy(ctx->iv, src_last_blk, ivsize); +- sg_pcopy_to_buffer(dev->first, dev->src_nents, req->iv, +- ivsize, dev->total - ivsize); +- } +- +- err = dev->load_data(dev, dev->sg_src, dev->sg_dst); +- if (!err) +- crypto_dma_start(dev); +- return err; +-} +- +-static int rk_ablk_start(struct rk_crypto_info *dev) +-{ +- struct skcipher_request *req = +- skcipher_request_cast(dev->async_req); +- unsigned long flags; ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(areq); ++ struct scatterlist *sgs, *sgd; + int err = 0; ++ int ivsize = crypto_skcipher_ivsize(tfm); ++ int offset; ++ u8 iv[AES_BLOCK_SIZE]; ++ u8 biv[AES_BLOCK_SIZE]; ++ u8 *ivtouse = areq->iv; ++ unsigned int len = areq->cryptlen; ++ unsigned int todo; ++ ++ ivsize = crypto_skcipher_ivsize(tfm); ++ if (areq->iv && crypto_skcipher_ivsize(tfm) > 0) { ++ if (rctx->mode & RK_CRYPTO_DEC) { ++ offset = areq->cryptlen - ivsize; ++ scatterwalk_map_and_copy(rctx->backup_iv, areq->src, ++ offset, ivsize, 0); ++ } ++ } + +- dev->left_bytes = req->cryptlen; +- dev->total = req->cryptlen; +- dev->sg_src = req->src; +- dev->first = req->src; +- dev->src_nents = sg_nents(req->src); +- dev->sg_dst = req->dst; +- dev->dst_nents = sg_nents(req->dst); +- dev->aligned = 1; +- +- spin_lock_irqsave(&dev->lock, flags); +- rk_ablk_hw_init(dev); +- err = rk_set_data_start(dev); +- spin_unlock_irqrestore(&dev->lock, flags); +- return err; +-} ++ sgs = areq->src; ++ sgd = areq->dst; + +-static void rk_iv_copyback(struct rk_crypto_info *dev) +-{ +- struct skcipher_request *req = +- skcipher_request_cast(dev->async_req); +- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); +- struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); +- u32 ivsize = crypto_skcipher_ivsize(tfm); +- +- /* Update the IV buffer to contain the next IV for encryption mode. */ +- if (!(ctx->mode & RK_CRYPTO_DEC)) { +- if (dev->aligned) { +- memcpy(req->iv, sg_virt(dev->sg_dst) + +- dev->sg_dst->length - ivsize, ivsize); ++ while (sgs && sgd && len) { ++ if (!sgs->length) { ++ sgs = sg_next(sgs); ++ sgd = sg_next(sgd); ++ continue; ++ } ++ if (rctx->mode & RK_CRYPTO_DEC) { ++ /* we backup last block of source to be used as IV at next step */ ++ offset = sgs->length - ivsize; ++ scatterwalk_map_and_copy(biv, sgs, offset, ivsize, 0); ++ } ++ if (sgs == sgd) { ++ err = dma_map_sg(ctx->dev->dev, sgs, 1, DMA_BIDIRECTIONAL); ++ if (err <= 0) { ++ err = -EINVAL; ++ goto theend_iv; ++ } ++ } else { ++ err = dma_map_sg(ctx->dev->dev, sgs, 1, DMA_TO_DEVICE); ++ if (err <= 0) { ++ err = -EINVAL; ++ goto theend_iv; ++ } ++ err = dma_map_sg(ctx->dev->dev, sgd, 1, DMA_FROM_DEVICE); ++ if (err <= 0) { ++ err = -EINVAL; ++ goto theend_sgs; ++ } ++ } ++ err = 0; ++ rk_ablk_hw_init(ctx->dev, areq); ++ if (ivsize) { ++ if (ivsize == DES_BLOCK_SIZE) ++ memcpy_toio(ctx->dev->reg + RK_CRYPTO_TDES_IV_0, ivtouse, ivsize); ++ else ++ memcpy_toio(ctx->dev->reg + RK_CRYPTO_AES_IV_0, ivtouse, ivsize); ++ } ++ reinit_completion(&ctx->dev->complete); ++ ctx->dev->status = 0; ++ ++ todo = min(sg_dma_len(sgs), len); ++ len -= todo; ++ crypto_dma_start(ctx->dev, sgs, sgd, todo / 4); ++ wait_for_completion_interruptible_timeout(&ctx->dev->complete, ++ msecs_to_jiffies(2000)); ++ if (!ctx->dev->status) { ++ dev_err(ctx->dev->dev, "DMA timeout\n"); ++ err = -EFAULT; ++ goto theend; ++ } ++ if (sgs == sgd) { ++ dma_unmap_sg(ctx->dev->dev, sgs, 1, DMA_BIDIRECTIONAL); ++ } else { ++ dma_unmap_sg(ctx->dev->dev, sgs, 1, DMA_TO_DEVICE); ++ dma_unmap_sg(ctx->dev->dev, sgd, 1, DMA_FROM_DEVICE); ++ } ++ if (rctx->mode & RK_CRYPTO_DEC) { ++ memcpy(iv, biv, ivsize); ++ ivtouse = iv; + } else { +- memcpy(req->iv, dev->addr_vir + +- dev->count - ivsize, ivsize); ++ offset = sgd->length - ivsize; ++ scatterwalk_map_and_copy(iv, sgd, offset, ivsize, 0); ++ ivtouse = iv; + } ++ sgs = sg_next(sgs); ++ sgd = sg_next(sgd); + } +-} +- +-static void rk_update_iv(struct rk_crypto_info *dev) +-{ +- struct skcipher_request *req = +- skcipher_request_cast(dev->async_req); +- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); +- struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); +- u32 ivsize = crypto_skcipher_ivsize(tfm); +- u8 *new_iv = NULL; + +- if (ctx->mode & RK_CRYPTO_DEC) { +- new_iv = ctx->iv; +- } else { +- new_iv = page_address(sg_page(dev->sg_dst)) + +- dev->sg_dst->offset + dev->sg_dst->length - ivsize; ++ if (areq->iv && ivsize > 0) { ++ offset = areq->cryptlen - ivsize; ++ if (rctx->mode & RK_CRYPTO_DEC) { ++ memcpy(areq->iv, rctx->backup_iv, ivsize); ++ memzero_explicit(rctx->backup_iv, ivsize); ++ } else { ++ scatterwalk_map_and_copy(areq->iv, areq->dst, offset, ++ ivsize, 0); ++ } + } + +- if (ivsize == DES_BLOCK_SIZE) +- memcpy_toio(dev->reg + RK_CRYPTO_TDES_IV_0, new_iv, ivsize); +- else if (ivsize == AES_BLOCK_SIZE) +- memcpy_toio(dev->reg + RK_CRYPTO_AES_IV_0, new_iv, ivsize); +-} ++theend: ++ local_bh_disable(); ++ crypto_finalize_skcipher_request(engine, areq, err); ++ local_bh_enable(); ++ return 0; + +-/* return: +- * true some err was occurred +- * fault no err, continue +- */ +-static int rk_ablk_rx(struct rk_crypto_info *dev) +-{ +- int err = 0; +- struct skcipher_request *req = +- skcipher_request_cast(dev->async_req); +- +- dev->unload_data(dev); +- if (!dev->aligned) { +- if (!sg_pcopy_from_buffer(req->dst, dev->dst_nents, +- dev->addr_vir, dev->count, +- dev->total - dev->left_bytes - +- dev->count)) { +- err = -EINVAL; +- goto out_rx; +- } +- } +- if (dev->left_bytes) { +- rk_update_iv(dev); +- if (dev->aligned) { +- if (sg_is_last(dev->sg_src)) { +- dev_err(dev->dev, "[%s:%d] Lack of data\n", +- __func__, __LINE__); +- err = -ENOMEM; +- goto out_rx; +- } +- dev->sg_src = sg_next(dev->sg_src); +- dev->sg_dst = sg_next(dev->sg_dst); +- } +- err = rk_set_data_start(dev); ++theend_sgs: ++ if (sgs == sgd) { ++ dma_unmap_sg(ctx->dev->dev, sgs, 1, DMA_BIDIRECTIONAL); + } else { +- rk_iv_copyback(dev); +- /* here show the calculation is over without any err */ +- dev->complete(dev->async_req, 0); +- tasklet_schedule(&dev->queue_task); ++ dma_unmap_sg(ctx->dev->dev, sgs, 1, DMA_TO_DEVICE); ++ dma_unmap_sg(ctx->dev->dev, sgd, 1, DMA_FROM_DEVICE); + } +-out_rx: ++theend_iv: + return err; + } + +@@ -378,26 +437,34 @@ static int rk_ablk_init_tfm(struct crypto_skcipher *tfm) + { + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); + struct skcipher_alg *alg = crypto_skcipher_alg(tfm); ++ const char *name = crypto_tfm_alg_name(&tfm->base); + struct rk_crypto_tmp *algt; + + algt = container_of(alg, struct rk_crypto_tmp, alg.skcipher); + + ctx->dev = algt->dev; +- ctx->dev->align_size = crypto_tfm_alg_alignmask(crypto_skcipher_tfm(tfm)) + 1; +- ctx->dev->start = rk_ablk_start; +- ctx->dev->update = rk_ablk_rx; +- ctx->dev->complete = rk_crypto_complete; +- ctx->dev->addr_vir = (char *)__get_free_page(GFP_KERNEL); + +- return ctx->dev->addr_vir ? ctx->dev->enable_clk(ctx->dev) : -ENOMEM; ++ ctx->fallback_tfm = crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); ++ if (IS_ERR(ctx->fallback_tfm)) { ++ dev_err(ctx->dev->dev, "ERROR: Cannot allocate fallback for %s %ld\n", ++ name, PTR_ERR(ctx->fallback_tfm)); ++ return PTR_ERR(ctx->fallback_tfm); ++ } ++ ++ tfm->reqsize = sizeof(struct rk_cipher_rctx) + ++ crypto_skcipher_reqsize(ctx->fallback_tfm); ++ ++ ctx->enginectx.op.do_one_request = rk_cipher_run; ++ ++ return 0; + } + + static void rk_ablk_exit_tfm(struct crypto_skcipher *tfm) + { + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); + +- free_page((unsigned long)ctx->dev->addr_vir); +- ctx->dev->disable_clk(ctx->dev); ++ memzero_explicit(ctx->key, ctx->keylen); ++ crypto_free_skcipher(ctx->fallback_tfm); + } + + struct rk_crypto_tmp rk_ecb_aes_alg = { +@@ -406,7 +473,7 @@ struct rk_crypto_tmp rk_ecb_aes_alg = { + .base.cra_name = "ecb(aes)", + .base.cra_driver_name = "ecb-aes-rk", + .base.cra_priority = 300, +- .base.cra_flags = CRYPTO_ALG_ASYNC, ++ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, + .base.cra_blocksize = AES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct rk_cipher_ctx), + .base.cra_alignmask = 0x0f, +@@ -428,7 +495,7 @@ struct rk_crypto_tmp rk_cbc_aes_alg = { + .base.cra_name = "cbc(aes)", + .base.cra_driver_name = "cbc-aes-rk", + .base.cra_priority = 300, +- .base.cra_flags = CRYPTO_ALG_ASYNC, ++ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, + .base.cra_blocksize = AES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct rk_cipher_ctx), + .base.cra_alignmask = 0x0f, +@@ -451,7 +518,7 @@ struct rk_crypto_tmp rk_ecb_des_alg = { + .base.cra_name = "ecb(des)", + .base.cra_driver_name = "ecb-des-rk", + .base.cra_priority = 300, +- .base.cra_flags = CRYPTO_ALG_ASYNC, ++ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct rk_cipher_ctx), + .base.cra_alignmask = 0x07, +@@ -473,7 +540,7 @@ struct rk_crypto_tmp rk_cbc_des_alg = { + .base.cra_name = "cbc(des)", + .base.cra_driver_name = "cbc-des-rk", + .base.cra_priority = 300, +- .base.cra_flags = CRYPTO_ALG_ASYNC, ++ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct rk_cipher_ctx), + .base.cra_alignmask = 0x07, +@@ -496,7 +563,7 @@ struct rk_crypto_tmp rk_ecb_des3_ede_alg = { + .base.cra_name = "ecb(des3_ede)", + .base.cra_driver_name = "ecb-des3-ede-rk", + .base.cra_priority = 300, +- .base.cra_flags = CRYPTO_ALG_ASYNC, ++ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct rk_cipher_ctx), + .base.cra_alignmask = 0x07, +@@ -518,7 +585,7 @@ struct rk_crypto_tmp rk_cbc_des3_ede_alg = { + .base.cra_name = "cbc(des3_ede)", + .base.cra_driver_name = "cbc-des3-ede-rk", + .base.cra_priority = 300, +- .base.cra_flags = CRYPTO_ALG_ASYNC, ++ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct rk_cipher_ctx), + .base.cra_alignmask = 0x07, +diff --git a/drivers/dio/dio.c b/drivers/dio/dio.c +index 0e5a5662d5a40..0a051d6568800 100644 +--- a/drivers/dio/dio.c ++++ b/drivers/dio/dio.c +@@ -109,6 +109,12 @@ static char dio_no_name[] = { 0 }; + + #endif /* CONFIG_DIO_CONSTANTS */ + ++static void dio_dev_release(struct device *dev) ++{ ++ struct dio_dev *ddev = container_of(dev, typeof(struct dio_dev), dev); ++ kfree(ddev); ++} ++ + int __init dio_find(int deviceid) + { + /* Called to find a DIO device before the full bus scan has run. +@@ -225,6 +231,7 @@ static int __init dio_init(void) + dev->bus = &dio_bus; + dev->dev.parent = &dio_bus.dev; + dev->dev.bus = &dio_bus_type; ++ dev->dev.release = dio_dev_release; + dev->scode = scode; + dev->resource.start = pa; + dev->resource.end = pa + DIO_SIZE(scode, va); +@@ -252,6 +259,7 @@ static int __init dio_init(void) + if (error) { + pr_err("DIO: Error registering device %s\n", + dev->name); ++ put_device(&dev->dev); + continue; + } + error = dio_create_sysfs_dev_files(dev); +diff --git a/drivers/dma/apple-admac.c b/drivers/dma/apple-admac.c +index a2cc520225d32..90f28bda29c8b 100644 +--- a/drivers/dma/apple-admac.c ++++ b/drivers/dma/apple-admac.c +@@ -21,6 +21,12 @@ + #define NCHANNELS_MAX 64 + #define IRQ_NOUTPUTS 4 + ++/* ++ * For allocation purposes we split the cache ++ * memory into blocks of fixed size (given in bytes). ++ */ ++#define SRAM_BLOCK 2048 ++ + #define RING_WRITE_SLOT GENMASK(1, 0) + #define RING_READ_SLOT GENMASK(5, 4) + #define RING_FULL BIT(9) +@@ -36,6 +42,9 @@ + #define REG_TX_STOP 0x0004 + #define REG_RX_START 0x0008 + #define REG_RX_STOP 0x000c ++#define REG_IMPRINT 0x0090 ++#define REG_TX_SRAM_SIZE 0x0094 ++#define REG_RX_SRAM_SIZE 0x0098 + + #define REG_CHAN_CTL(ch) (0x8000 + (ch) * 0x200) + #define REG_CHAN_CTL_RST_RINGS BIT(0) +@@ -53,7 +62,9 @@ + #define BUS_WIDTH_FRAME_2_WORDS 0x10 + #define BUS_WIDTH_FRAME_4_WORDS 0x20 + +-#define CHAN_BUFSIZE 0x8000 ++#define REG_CHAN_SRAM_CARVEOUT(ch) (0x8050 + (ch) * 0x200) ++#define CHAN_SRAM_CARVEOUT_SIZE GENMASK(31, 16) ++#define CHAN_SRAM_CARVEOUT_BASE GENMASK(15, 0) + + #define REG_CHAN_FIFOCTL(ch) (0x8054 + (ch) * 0x200) + #define CHAN_FIFOCTL_LIMIT GENMASK(31, 16) +@@ -76,6 +87,8 @@ struct admac_chan { + struct dma_chan chan; + struct tasklet_struct tasklet; + ++ u32 carveout; ++ + spinlock_t lock; + struct admac_tx *current_tx; + int nperiod_acks; +@@ -92,12 +105,24 @@ struct admac_chan { + struct list_head to_free; + }; + ++struct admac_sram { ++ u32 size; ++ /* ++ * SRAM_CARVEOUT has 16-bit fields, so the SRAM cannot be larger than ++ * 64K and a 32-bit bitfield over 2K blocks covers it. ++ */ ++ u32 allocated; ++}; ++ + struct admac_data { + struct dma_device dma; + struct device *dev; + __iomem void *base; + struct reset_control *rstc; + ++ struct mutex cache_alloc_lock; ++ struct admac_sram txcache, rxcache; ++ + int irq; + int irq_index; + int nchannels; +@@ -118,6 +143,60 @@ struct admac_tx { + struct list_head node; + }; + ++static int admac_alloc_sram_carveout(struct admac_data *ad, ++ enum dma_transfer_direction dir, ++ u32 *out) ++{ ++ struct admac_sram *sram; ++ int i, ret = 0, nblocks; ++ ++ if (dir == DMA_MEM_TO_DEV) ++ sram = &ad->txcache; ++ else ++ sram = &ad->rxcache; ++ ++ mutex_lock(&ad->cache_alloc_lock); ++ ++ nblocks = sram->size / SRAM_BLOCK; ++ for (i = 0; i < nblocks; i++) ++ if (!(sram->allocated & BIT(i))) ++ break; ++ ++ if (i < nblocks) { ++ *out = FIELD_PREP(CHAN_SRAM_CARVEOUT_BASE, i * SRAM_BLOCK) | ++ FIELD_PREP(CHAN_SRAM_CARVEOUT_SIZE, SRAM_BLOCK); ++ sram->allocated |= BIT(i); ++ } else { ++ ret = -EBUSY; ++ } ++ ++ mutex_unlock(&ad->cache_alloc_lock); ++ ++ return ret; ++} ++ ++static void admac_free_sram_carveout(struct admac_data *ad, ++ enum dma_transfer_direction dir, ++ u32 carveout) ++{ ++ struct admac_sram *sram; ++ u32 base = FIELD_GET(CHAN_SRAM_CARVEOUT_BASE, carveout); ++ int i; ++ ++ if (dir == DMA_MEM_TO_DEV) ++ sram = &ad->txcache; ++ else ++ sram = &ad->rxcache; ++ ++ if (WARN_ON(base >= sram->size)) ++ return; ++ ++ mutex_lock(&ad->cache_alloc_lock); ++ i = base / SRAM_BLOCK; ++ sram->allocated &= ~BIT(i); ++ mutex_unlock(&ad->cache_alloc_lock); ++} ++ + static void admac_modify(struct admac_data *ad, int reg, u32 mask, u32 val) + { + void __iomem *addr = ad->base + reg; +@@ -466,15 +545,28 @@ static void admac_synchronize(struct dma_chan *chan) + static int admac_alloc_chan_resources(struct dma_chan *chan) + { + struct admac_chan *adchan = to_admac_chan(chan); ++ struct admac_data *ad = adchan->host; ++ int ret; + + dma_cookie_init(&adchan->chan); ++ ret = admac_alloc_sram_carveout(ad, admac_chan_direction(adchan->no), ++ &adchan->carveout); ++ if (ret < 0) ++ return ret; ++ ++ writel_relaxed(adchan->carveout, ++ ad->base + REG_CHAN_SRAM_CARVEOUT(adchan->no)); + return 0; + } + + static void admac_free_chan_resources(struct dma_chan *chan) + { ++ struct admac_chan *adchan = to_admac_chan(chan); ++ + admac_terminate_all(chan); + admac_synchronize(chan); ++ admac_free_sram_carveout(adchan->host, admac_chan_direction(adchan->no), ++ adchan->carveout); + } + + static struct dma_chan *admac_dma_of_xlate(struct of_phandle_args *dma_spec, +@@ -712,6 +804,7 @@ static int admac_probe(struct platform_device *pdev) + platform_set_drvdata(pdev, ad); + ad->dev = &pdev->dev; + ad->nchannels = nchannels; ++ mutex_init(&ad->cache_alloc_lock); + + /* + * The controller has 4 IRQ outputs. Try them all until +@@ -801,6 +894,13 @@ static int admac_probe(struct platform_device *pdev) + goto free_irq; + } + ++ ad->txcache.size = readl_relaxed(ad->base + REG_TX_SRAM_SIZE); ++ ad->rxcache.size = readl_relaxed(ad->base + REG_RX_SRAM_SIZE); ++ ++ dev_info(&pdev->dev, "Audio DMA Controller\n"); ++ dev_info(&pdev->dev, "imprint %x TX cache %u RX cache %u\n", ++ readl_relaxed(ad->base + REG_IMPRINT), ad->txcache.size, ad->rxcache.size); ++ + return 0; + + free_irq: +diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c +index 7269bd54554f6..3229dfc786507 100644 +--- a/drivers/dma/idxd/sysfs.c ++++ b/drivers/dma/idxd/sysfs.c +@@ -528,6 +528,22 @@ static bool idxd_group_attr_progress_limit_invisible(struct attribute *attr, + !idxd->hw.group_cap.progress_limit; + } + ++static bool idxd_group_attr_read_buffers_invisible(struct attribute *attr, ++ struct idxd_device *idxd) ++{ ++ /* ++ * Intel IAA does not support Read Buffer allocation control, ++ * make these attributes invisible. ++ */ ++ return (attr == &dev_attr_group_use_token_limit.attr || ++ attr == &dev_attr_group_use_read_buffer_limit.attr || ++ attr == &dev_attr_group_tokens_allowed.attr || ++ attr == &dev_attr_group_read_buffers_allowed.attr || ++ attr == &dev_attr_group_tokens_reserved.attr || ++ attr == &dev_attr_group_read_buffers_reserved.attr) && ++ idxd->data->type == IDXD_TYPE_IAX; ++} ++ + static umode_t idxd_group_attr_visible(struct kobject *kobj, + struct attribute *attr, int n) + { +@@ -538,6 +554,9 @@ static umode_t idxd_group_attr_visible(struct kobject *kobj, + if (idxd_group_attr_progress_limit_invisible(attr, idxd)) + return 0; + ++ if (idxd_group_attr_read_buffers_invisible(attr, idxd)) ++ return 0; ++ + return attr->mode; + } + +@@ -1233,6 +1252,14 @@ static bool idxd_wq_attr_op_config_invisible(struct attribute *attr, + !idxd->hw.wq_cap.op_config; + } + ++static bool idxd_wq_attr_max_batch_size_invisible(struct attribute *attr, ++ struct idxd_device *idxd) ++{ ++ /* Intel IAA does not support batch processing, make it invisible */ ++ return attr == &dev_attr_wq_max_batch_size.attr && ++ idxd->data->type == IDXD_TYPE_IAX; ++} ++ + static umode_t idxd_wq_attr_visible(struct kobject *kobj, + struct attribute *attr, int n) + { +@@ -1243,6 +1270,9 @@ static umode_t idxd_wq_attr_visible(struct kobject *kobj, + if (idxd_wq_attr_op_config_invisible(attr, idxd)) + return 0; + ++ if (idxd_wq_attr_max_batch_size_invisible(attr, idxd)) ++ return 0; ++ + return attr->mode; + } + +@@ -1533,6 +1563,43 @@ static ssize_t cmd_status_store(struct device *dev, struct device_attribute *att + } + static DEVICE_ATTR_RW(cmd_status); + ++static bool idxd_device_attr_max_batch_size_invisible(struct attribute *attr, ++ struct idxd_device *idxd) ++{ ++ /* Intel IAA does not support batch processing, make it invisible */ ++ return attr == &dev_attr_max_batch_size.attr && ++ idxd->data->type == IDXD_TYPE_IAX; ++} ++ ++static bool idxd_device_attr_read_buffers_invisible(struct attribute *attr, ++ struct idxd_device *idxd) ++{ ++ /* ++ * Intel IAA does not support Read Buffer allocation control, ++ * make these attributes invisible. ++ */ ++ return (attr == &dev_attr_max_tokens.attr || ++ attr == &dev_attr_max_read_buffers.attr || ++ attr == &dev_attr_token_limit.attr || ++ attr == &dev_attr_read_buffer_limit.attr) && ++ idxd->data->type == IDXD_TYPE_IAX; ++} ++ ++static umode_t idxd_device_attr_visible(struct kobject *kobj, ++ struct attribute *attr, int n) ++{ ++ struct device *dev = container_of(kobj, struct device, kobj); ++ struct idxd_device *idxd = confdev_to_idxd(dev); ++ ++ if (idxd_device_attr_max_batch_size_invisible(attr, idxd)) ++ return 0; ++ ++ if (idxd_device_attr_read_buffers_invisible(attr, idxd)) ++ return 0; ++ ++ return attr->mode; ++} ++ + static struct attribute *idxd_device_attributes[] = { + &dev_attr_version.attr, + &dev_attr_max_groups.attr, +@@ -1560,6 +1627,7 @@ static struct attribute *idxd_device_attributes[] = { + + static const struct attribute_group idxd_device_attribute_group = { + .attrs = idxd_device_attributes, ++ .is_visible = idxd_device_attr_visible, + }; + + static const struct attribute_group *idxd_attribute_groups[] = { +diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c +index a22ea053f8e1c..8af4d2523194a 100644 +--- a/drivers/edac/i10nm_base.c ++++ b/drivers/edac/i10nm_base.c +@@ -304,11 +304,10 @@ static struct pci_dev *pci_get_dev_wrapper(int dom, unsigned int bus, + if (unlikely(pci_enable_device(pdev) < 0)) { + edac_dbg(2, "Failed to enable device %02x:%02x.%x\n", + bus, dev, fun); ++ pci_dev_put(pdev); + return NULL; + } + +- pci_dev_get(pdev); +- + return pdev; + } + +diff --git a/drivers/extcon/extcon-usbc-tusb320.c b/drivers/extcon/extcon-usbc-tusb320.c +index 2a120d8d3c272..9dfa545427ca1 100644 +--- a/drivers/extcon/extcon-usbc-tusb320.c ++++ b/drivers/extcon/extcon-usbc-tusb320.c +@@ -313,9 +313,9 @@ static void tusb320_typec_irq_handler(struct tusb320_priv *priv, u8 reg9) + typec_set_pwr_opmode(port, TYPEC_PWR_MODE_USB); + } + +-static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) ++static irqreturn_t tusb320_state_update_handler(struct tusb320_priv *priv, ++ bool force_update) + { +- struct tusb320_priv *priv = dev_id; + unsigned int reg; + + if (regmap_read(priv->regmap, TUSB320_REG9, ®)) { +@@ -323,7 +323,7 @@ static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) + return IRQ_NONE; + } + +- if (!(reg & TUSB320_REG9_INTERRUPT_STATUS)) ++ if (!force_update && !(reg & TUSB320_REG9_INTERRUPT_STATUS)) + return IRQ_NONE; + + tusb320_extcon_irq_handler(priv, reg); +@@ -340,6 +340,13 @@ static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) + return IRQ_HANDLED; + } + ++static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) ++{ ++ struct tusb320_priv *priv = dev_id; ++ ++ return tusb320_state_update_handler(priv, false); ++} ++ + static const struct regmap_config tusb320_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +@@ -466,7 +473,7 @@ static int tusb320_probe(struct i2c_client *client, + return ret; + + /* update initial state */ +- tusb320_irq_handler(client->irq, priv); ++ tusb320_state_update_handler(priv, true); + + /* Reset chip to its default state */ + ret = tusb320_reset(priv); +@@ -477,7 +484,7 @@ static int tusb320_probe(struct i2c_client *client, + * State and polarity might change after a reset, so update + * them again and make sure the interrupt status bit is cleared. + */ +- tusb320_irq_handler(client->irq, priv); ++ tusb320_state_update_handler(priv, true); + + ret = devm_request_threaded_irq(priv->dev, client->irq, NULL, + tusb320_irq_handler, +diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c +index 4b8978b254f9a..dba315f675bc7 100644 +--- a/drivers/firmware/raspberrypi.c ++++ b/drivers/firmware/raspberrypi.c +@@ -272,6 +272,7 @@ static int rpi_firmware_probe(struct platform_device *pdev) + int ret = PTR_ERR(fw->chan); + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to get mbox channel: %d\n", ret); ++ kfree(fw); + return ret; + } + +diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c +index ebc32bbd9b833..6281e7153b475 100644 +--- a/drivers/firmware/ti_sci.c ++++ b/drivers/firmware/ti_sci.c +@@ -429,15 +429,14 @@ static inline int ti_sci_do_xfer(struct ti_sci_info *info, + * during noirq phase, so we must manually poll the completion. + */ + ret = read_poll_timeout_atomic(try_wait_for_completion, done_state, +- true, 1, ++ done_state, 1, + info->desc->max_rx_timeout_ms * 1000, + false, &xfer->done); + } + +- if (ret == -ETIMEDOUT || !done_state) { ++ if (ret == -ETIMEDOUT) + dev_err(dev, "Mbox timedout in resp(caller: %pS)\n", + (void *)_RET_IP_); +- } + + /* + * NOTE: we might prefer not to need the mailbox ticker to manage the +diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c +index 0cb6b468f364f..6ab1cf489d035 100644 +--- a/drivers/gpio/gpiolib-cdev.c ++++ b/drivers/gpio/gpiolib-cdev.c +@@ -55,6 +55,50 @@ static_assert(IS_ALIGNED(sizeof(struct gpio_v2_line_values), 8)); + * interface to gpiolib GPIOs via ioctl()s. + */ + ++typedef __poll_t (*poll_fn)(struct file *, struct poll_table_struct *); ++typedef long (*ioctl_fn)(struct file *, unsigned int, unsigned long); ++typedef ssize_t (*read_fn)(struct file *, char __user *, ++ size_t count, loff_t *); ++ ++static __poll_t call_poll_locked(struct file *file, ++ struct poll_table_struct *wait, ++ struct gpio_device *gdev, poll_fn func) ++{ ++ __poll_t ret; ++ ++ down_read(&gdev->sem); ++ ret = func(file, wait); ++ up_read(&gdev->sem); ++ ++ return ret; ++} ++ ++static long call_ioctl_locked(struct file *file, unsigned int cmd, ++ unsigned long arg, struct gpio_device *gdev, ++ ioctl_fn func) ++{ ++ long ret; ++ ++ down_read(&gdev->sem); ++ ret = func(file, cmd, arg); ++ up_read(&gdev->sem); ++ ++ return ret; ++} ++ ++static ssize_t call_read_locked(struct file *file, char __user *buf, ++ size_t count, loff_t *f_ps, ++ struct gpio_device *gdev, read_fn func) ++{ ++ ssize_t ret; ++ ++ down_read(&gdev->sem); ++ ret = func(file, buf, count, f_ps); ++ up_read(&gdev->sem); ++ ++ return ret; ++} ++ + /* + * GPIO line handle management + */ +@@ -191,8 +235,8 @@ static long linehandle_set_config(struct linehandle_state *lh, + return 0; + } + +-static long linehandle_ioctl(struct file *file, unsigned int cmd, +- unsigned long arg) ++static long linehandle_ioctl_unlocked(struct file *file, unsigned int cmd, ++ unsigned long arg) + { + struct linehandle_state *lh = file->private_data; + void __user *ip = (void __user *)arg; +@@ -201,6 +245,9 @@ static long linehandle_ioctl(struct file *file, unsigned int cmd, + unsigned int i; + int ret; + ++ if (!lh->gdev->chip) ++ return -ENODEV; ++ + switch (cmd) { + case GPIOHANDLE_GET_LINE_VALUES_IOCTL: + /* NOTE: It's okay to read values of output lines */ +@@ -247,6 +294,15 @@ static long linehandle_ioctl(struct file *file, unsigned int cmd, + } + } + ++static long linehandle_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct linehandle_state *lh = file->private_data; ++ ++ return call_ioctl_locked(file, cmd, arg, lh->gdev, ++ linehandle_ioctl_unlocked); ++} ++ + #ifdef CONFIG_COMPAT + static long linehandle_ioctl_compat(struct file *file, unsigned int cmd, + unsigned long arg) +@@ -1378,12 +1434,15 @@ static long linereq_set_config(struct linereq *lr, void __user *ip) + return ret; + } + +-static long linereq_ioctl(struct file *file, unsigned int cmd, +- unsigned long arg) ++static long linereq_ioctl_unlocked(struct file *file, unsigned int cmd, ++ unsigned long arg) + { + struct linereq *lr = file->private_data; + void __user *ip = (void __user *)arg; + ++ if (!lr->gdev->chip) ++ return -ENODEV; ++ + switch (cmd) { + case GPIO_V2_LINE_GET_VALUES_IOCTL: + return linereq_get_values(lr, ip); +@@ -1396,6 +1455,15 @@ static long linereq_ioctl(struct file *file, unsigned int cmd, + } + } + ++static long linereq_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct linereq *lr = file->private_data; ++ ++ return call_ioctl_locked(file, cmd, arg, lr->gdev, ++ linereq_ioctl_unlocked); ++} ++ + #ifdef CONFIG_COMPAT + static long linereq_ioctl_compat(struct file *file, unsigned int cmd, + unsigned long arg) +@@ -1404,12 +1472,15 @@ static long linereq_ioctl_compat(struct file *file, unsigned int cmd, + } + #endif + +-static __poll_t linereq_poll(struct file *file, +- struct poll_table_struct *wait) ++static __poll_t linereq_poll_unlocked(struct file *file, ++ struct poll_table_struct *wait) + { + struct linereq *lr = file->private_data; + __poll_t events = 0; + ++ if (!lr->gdev->chip) ++ return EPOLLHUP | EPOLLERR; ++ + poll_wait(file, &lr->wait, wait); + + if (!kfifo_is_empty_spinlocked_noirqsave(&lr->events, +@@ -1419,16 +1490,25 @@ static __poll_t linereq_poll(struct file *file, + return events; + } + +-static ssize_t linereq_read(struct file *file, +- char __user *buf, +- size_t count, +- loff_t *f_ps) ++static __poll_t linereq_poll(struct file *file, ++ struct poll_table_struct *wait) ++{ ++ struct linereq *lr = file->private_data; ++ ++ return call_poll_locked(file, wait, lr->gdev, linereq_poll_unlocked); ++} ++ ++static ssize_t linereq_read_unlocked(struct file *file, char __user *buf, ++ size_t count, loff_t *f_ps) + { + struct linereq *lr = file->private_data; + struct gpio_v2_line_event le; + ssize_t bytes_read = 0; + int ret; + ++ if (!lr->gdev->chip) ++ return -ENODEV; ++ + if (count < sizeof(le)) + return -EINVAL; + +@@ -1473,6 +1553,15 @@ static ssize_t linereq_read(struct file *file, + return bytes_read; + } + ++static ssize_t linereq_read(struct file *file, char __user *buf, ++ size_t count, loff_t *f_ps) ++{ ++ struct linereq *lr = file->private_data; ++ ++ return call_read_locked(file, buf, count, f_ps, lr->gdev, ++ linereq_read_unlocked); ++} ++ + static void linereq_free(struct linereq *lr) + { + unsigned int i; +@@ -1710,12 +1799,15 @@ struct lineevent_state { + (GPIOEVENT_REQUEST_RISING_EDGE | \ + GPIOEVENT_REQUEST_FALLING_EDGE) + +-static __poll_t lineevent_poll(struct file *file, +- struct poll_table_struct *wait) ++static __poll_t lineevent_poll_unlocked(struct file *file, ++ struct poll_table_struct *wait) + { + struct lineevent_state *le = file->private_data; + __poll_t events = 0; + ++ if (!le->gdev->chip) ++ return EPOLLHUP | EPOLLERR; ++ + poll_wait(file, &le->wait, wait); + + if (!kfifo_is_empty_spinlocked_noirqsave(&le->events, &le->wait.lock)) +@@ -1724,15 +1816,21 @@ static __poll_t lineevent_poll(struct file *file, + return events; + } + ++static __poll_t lineevent_poll(struct file *file, ++ struct poll_table_struct *wait) ++{ ++ struct lineevent_state *le = file->private_data; ++ ++ return call_poll_locked(file, wait, le->gdev, lineevent_poll_unlocked); ++} ++ + struct compat_gpioeevent_data { + compat_u64 timestamp; + u32 id; + }; + +-static ssize_t lineevent_read(struct file *file, +- char __user *buf, +- size_t count, +- loff_t *f_ps) ++static ssize_t lineevent_read_unlocked(struct file *file, char __user *buf, ++ size_t count, loff_t *f_ps) + { + struct lineevent_state *le = file->private_data; + struct gpioevent_data ge; +@@ -1740,6 +1838,9 @@ static ssize_t lineevent_read(struct file *file, + ssize_t ge_size; + int ret; + ++ if (!le->gdev->chip) ++ return -ENODEV; ++ + /* + * When compatible system call is being used the struct gpioevent_data, + * in case of at least ia32, has different size due to the alignment +@@ -1797,6 +1898,15 @@ static ssize_t lineevent_read(struct file *file, + return bytes_read; + } + ++static ssize_t lineevent_read(struct file *file, char __user *buf, ++ size_t count, loff_t *f_ps) ++{ ++ struct lineevent_state *le = file->private_data; ++ ++ return call_read_locked(file, buf, count, f_ps, le->gdev, ++ lineevent_read_unlocked); ++} ++ + static void lineevent_free(struct lineevent_state *le) + { + if (le->irq) +@@ -1814,13 +1924,16 @@ static int lineevent_release(struct inode *inode, struct file *file) + return 0; + } + +-static long lineevent_ioctl(struct file *file, unsigned int cmd, +- unsigned long arg) ++static long lineevent_ioctl_unlocked(struct file *file, unsigned int cmd, ++ unsigned long arg) + { + struct lineevent_state *le = file->private_data; + void __user *ip = (void __user *)arg; + struct gpiohandle_data ghd; + ++ if (!le->gdev->chip) ++ return -ENODEV; ++ + /* + * We can get the value for an event line but not set it, + * because it is input by definition. +@@ -1843,6 +1956,15 @@ static long lineevent_ioctl(struct file *file, unsigned int cmd, + return -EINVAL; + } + ++static long lineevent_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct lineevent_state *le = file->private_data; ++ ++ return call_ioctl_locked(file, cmd, arg, le->gdev, ++ lineevent_ioctl_unlocked); ++} ++ + #ifdef CONFIG_COMPAT + static long lineevent_ioctl_compat(struct file *file, unsigned int cmd, + unsigned long arg) +@@ -2401,12 +2523,15 @@ static int lineinfo_changed_notify(struct notifier_block *nb, + return NOTIFY_OK; + } + +-static __poll_t lineinfo_watch_poll(struct file *file, +- struct poll_table_struct *pollt) ++static __poll_t lineinfo_watch_poll_unlocked(struct file *file, ++ struct poll_table_struct *pollt) + { + struct gpio_chardev_data *cdev = file->private_data; + __poll_t events = 0; + ++ if (!cdev->gdev->chip) ++ return EPOLLHUP | EPOLLERR; ++ + poll_wait(file, &cdev->wait, pollt); + + if (!kfifo_is_empty_spinlocked_noirqsave(&cdev->events, +@@ -2416,8 +2541,17 @@ static __poll_t lineinfo_watch_poll(struct file *file, + return events; + } + +-static ssize_t lineinfo_watch_read(struct file *file, char __user *buf, +- size_t count, loff_t *off) ++static __poll_t lineinfo_watch_poll(struct file *file, ++ struct poll_table_struct *pollt) ++{ ++ struct gpio_chardev_data *cdev = file->private_data; ++ ++ return call_poll_locked(file, pollt, cdev->gdev, ++ lineinfo_watch_poll_unlocked); ++} ++ ++static ssize_t lineinfo_watch_read_unlocked(struct file *file, char __user *buf, ++ size_t count, loff_t *off) + { + struct gpio_chardev_data *cdev = file->private_data; + struct gpio_v2_line_info_changed event; +@@ -2425,6 +2559,9 @@ static ssize_t lineinfo_watch_read(struct file *file, char __user *buf, + int ret; + size_t event_size; + ++ if (!cdev->gdev->chip) ++ return -ENODEV; ++ + #ifndef CONFIG_GPIO_CDEV_V1 + event_size = sizeof(struct gpio_v2_line_info_changed); + if (count < event_size) +@@ -2492,6 +2629,15 @@ static ssize_t lineinfo_watch_read(struct file *file, char __user *buf, + return bytes_read; + } + ++static ssize_t lineinfo_watch_read(struct file *file, char __user *buf, ++ size_t count, loff_t *off) ++{ ++ struct gpio_chardev_data *cdev = file->private_data; ++ ++ return call_read_locked(file, buf, count, off, cdev->gdev, ++ lineinfo_watch_read_unlocked); ++} ++ + /** + * gpio_chrdev_open() - open the chardev for ioctl operations + * @inode: inode for this chardev +@@ -2505,13 +2651,17 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file) + struct gpio_chardev_data *cdev; + int ret = -ENOMEM; + ++ down_read(&gdev->sem); ++ + /* Fail on open if the backing gpiochip is gone */ +- if (!gdev->chip) +- return -ENODEV; ++ if (!gdev->chip) { ++ ret = -ENODEV; ++ goto out_unlock; ++ } + + cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); + if (!cdev) +- return -ENOMEM; ++ goto out_unlock; + + cdev->watched_lines = bitmap_zalloc(gdev->chip->ngpio, GFP_KERNEL); + if (!cdev->watched_lines) +@@ -2534,6 +2684,8 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file) + if (ret) + goto out_unregister_notifier; + ++ up_read(&gdev->sem); ++ + return ret; + + out_unregister_notifier: +@@ -2543,6 +2695,8 @@ out_free_bitmap: + bitmap_free(cdev->watched_lines); + out_free_cdev: + kfree(cdev); ++out_unlock: ++ up_read(&gdev->sem); + return ret; + } + +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index a70522aef3557..5974cfc61b417 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -735,6 +735,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, + spin_unlock_irqrestore(&gpio_lock, flags); + + BLOCKING_INIT_NOTIFIER_HEAD(&gdev->notifier); ++ init_rwsem(&gdev->sem); + + #ifdef CONFIG_PINCTRL + INIT_LIST_HEAD(&gdev->pin_ranges); +@@ -875,6 +876,8 @@ void gpiochip_remove(struct gpio_chip *gc) + unsigned long flags; + unsigned int i; + ++ down_write(&gdev->sem); ++ + /* FIXME: should the legacy sysfs handling be moved to gpio_device? */ + gpiochip_sysfs_unregister(gdev); + gpiochip_free_hogs(gc); +@@ -909,6 +912,7 @@ void gpiochip_remove(struct gpio_chip *gc) + * gone. + */ + gcdev_unregister(gdev); ++ up_write(&gdev->sem); + put_device(&gdev->dev); + } + EXPORT_SYMBOL_GPL(gpiochip_remove); +diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h +index d900ecdbac46d..9ad68a0adf4a8 100644 +--- a/drivers/gpio/gpiolib.h ++++ b/drivers/gpio/gpiolib.h +@@ -15,6 +15,7 @@ + #include <linux/device.h> + #include <linux/module.h> + #include <linux/cdev.h> ++#include <linux/rwsem.h> + + #define GPIOCHIP_NAME "gpiochip" + +@@ -39,6 +40,9 @@ + * @list: links gpio_device:s together for traversal + * @notifier: used to notify subscribers about lines being requested, released + * or reconfigured ++ * @sem: protects the structure from a NULL-pointer dereference of @chip by ++ * user-space operations when the device gets unregistered during ++ * a hot-unplug event + * @pin_ranges: range of pins served by the GPIO driver + * + * This state container holds most of the runtime variable data +@@ -60,6 +64,7 @@ struct gpio_device { + void *data; + struct list_head list; + struct blocking_notifier_head notifier; ++ struct rw_semaphore sem; + + #ifdef CONFIG_PINCTRL + /* +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +index 1f76e27f1a354..fe87b3402f06a 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +@@ -2256,7 +2256,7 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev, + + ret = drm_vma_node_allow(&obj->vma_node, drm_priv); + if (ret) { +- kfree(mem); ++ kfree(*mem); + return ret; + } + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +index e363f56c72af1..30c28a69e847d 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +@@ -317,6 +317,7 @@ static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev) + + if (!found) + return false; ++ pci_dev_put(pdev); + + adev->bios = kmalloc(size, GFP_KERNEL); + if (!adev->bios) { +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index f1e9663b40510..913f22d41673d 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -2462,6 +2462,11 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) + if (!amdgpu_sriov_vf(adev)) { + struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev); + ++ if (WARN_ON(!hive)) { ++ r = -ENOENT; ++ goto init_failed; ++ } ++ + if (!hive->reset_domain || + !amdgpu_reset_get_reset_domain(hive->reset_domain)) { + r = -ENOENT; +@@ -5027,6 +5032,8 @@ static void amdgpu_device_resume_display_audio(struct amdgpu_device *adev) + pm_runtime_enable(&(p->dev)); + pm_runtime_resume(&(p->dev)); + } ++ ++ pci_dev_put(p); + } + + static int amdgpu_device_suspend_display_audio(struct amdgpu_device *adev) +@@ -5065,6 +5072,7 @@ static int amdgpu_device_suspend_display_audio(struct amdgpu_device *adev) + + if (expires < ktime_get_mono_fast_ns()) { + dev_warn(adev->dev, "failed to suspend display audio\n"); ++ pci_dev_put(p); + /* TODO: abort the succeeding gpu reset? */ + return -ETIMEDOUT; + } +@@ -5072,6 +5080,7 @@ static int amdgpu_device_suspend_display_audio(struct amdgpu_device *adev) + + pm_runtime_disable(&(p->dev)); + ++ pci_dev_put(p); + return 0; + } + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +index 49c4347d154ce..2b9d806e23afb 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +@@ -75,6 +75,8 @@ struct amdgpu_vf_error_buffer { + uint64_t data[AMDGPU_VF_ERROR_ENTRY_SIZE]; + }; + ++enum idh_request; ++ + /** + * struct amdgpu_virt_ops - amdgpu device virt operations + */ +@@ -84,7 +86,8 @@ struct amdgpu_virt_ops { + int (*req_init_data)(struct amdgpu_device *adev); + int (*reset_gpu)(struct amdgpu_device *adev); + int (*wait_reset)(struct amdgpu_device *adev); +- void (*trans_msg)(struct amdgpu_device *adev, u32 req, u32 data1, u32 data2, u32 data3); ++ void (*trans_msg)(struct amdgpu_device *adev, enum idh_request req, ++ u32 data1, u32 data2, u32 data3); + }; + + /* +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +index 47159e9a08848..4b9e7b050ccd2 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +@@ -386,7 +386,6 @@ struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev) + 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; + } +@@ -410,7 +409,6 @@ struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev) + dev_err(adev->dev, "XGMI: failed initializing reset domain for xgmi hive\n"); + ret = -ENOMEM; + kobject_put(&hive->kobj); +- kfree(hive); + hive = NULL; + goto pro_end; + } +diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c +index b3fba8dea63ca..6853b93ac82e7 100644 +--- a/drivers/gpu/drm/amd/amdgpu/nv.c ++++ b/drivers/gpu/drm/amd/amdgpu/nv.c +@@ -82,10 +82,10 @@ static const struct amdgpu_video_codecs nv_video_codecs_encode = + /* Navi1x */ + static const struct amdgpu_video_codec_info nv_video_codecs_decode_array[] = + { +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4906, 3)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4906, 5)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4906, 4)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, +@@ -100,10 +100,10 @@ static const struct amdgpu_video_codecs nv_video_codecs_decode = + /* Sienna Cichlid */ + static const struct amdgpu_video_codec_info sc_video_codecs_decode_array[] = + { +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4906, 3)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4906, 5)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4906, 4)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, +@@ -125,10 +125,10 @@ static struct amdgpu_video_codec_info sriov_sc_video_codecs_encode_array[] = + + static struct amdgpu_video_codec_info sriov_sc_video_codecs_decode_array[] = + { +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4906, 3)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4906, 5)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4906, 4)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, +@@ -149,7 +149,7 @@ static struct amdgpu_video_codecs sriov_sc_video_codecs_decode = + + /* Beige Goby*/ + static const struct amdgpu_video_codec_info bg_video_codecs_decode_array[] = { +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, + }; +@@ -166,7 +166,7 @@ static const struct amdgpu_video_codecs bg_video_codecs_encode = { + + /* Yellow Carp*/ + static const struct amdgpu_video_codec_info yc_video_codecs_decode_array[] = { +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, +diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c +index e3b2b6b4f1a66..7cd17dda32ceb 100644 +--- a/drivers/gpu/drm/amd/amdgpu/soc15.c ++++ b/drivers/gpu/drm/amd/amdgpu/soc15.c +@@ -103,10 +103,10 @@ static const struct amdgpu_video_codecs vega_video_codecs_encode = + /* Vega */ + static const struct amdgpu_video_codec_info vega_video_codecs_decode_array[] = + { +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4906, 3)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4906, 5)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4906, 4)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 4096, 186)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, + }; +@@ -120,10 +120,10 @@ static const struct amdgpu_video_codecs vega_video_codecs_decode = + /* Raven */ + static const struct amdgpu_video_codec_info rv_video_codecs_decode_array[] = + { +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4906, 3)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4906, 5)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4906, 4)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 4096, 186)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 4096, 4096, 0)}, +@@ -138,10 +138,10 @@ static const struct amdgpu_video_codecs rv_video_codecs_decode = + /* Renoir, Arcturus */ + static const struct amdgpu_video_codec_info rn_video_codecs_decode_array[] = + { +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4906, 3)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4906, 5)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4906, 4)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, +diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c +index e08044008186e..8b297ade69a24 100644 +--- a/drivers/gpu/drm/amd/amdgpu/soc21.c ++++ b/drivers/gpu/drm/amd/amdgpu/soc21.c +@@ -61,7 +61,7 @@ static const struct amdgpu_video_codecs vcn_4_0_0_video_codecs_encode = + + static const struct amdgpu_video_codec_info vcn_4_0_0_video_codecs_decode_array[] = + { +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, +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 f0b01c8dc4a6b..f72c013d3a5b0 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 +@@ -42,39 +42,6 @@ + #include "dm_helpers.h" + #include "ddc_service_types.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 +@@ -149,8 +116,6 @@ 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/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +index e0c8d6f09bb4b..074e70a5c458e 100644 +--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c ++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +@@ -462,6 +462,7 @@ static enum bp_result get_gpio_i2c_info( + uint32_t count = 0; + unsigned int table_index = 0; + bool find_valid = false; ++ struct atom_gpio_pin_assignment *pin; + + if (!info) + return BP_RESULT_BADINPUT; +@@ -489,20 +490,17 @@ static enum bp_result get_gpio_i2c_info( + - sizeof(struct atom_common_table_header)) + / sizeof(struct atom_gpio_pin_assignment); + ++ pin = (struct atom_gpio_pin_assignment *) header->gpio_pin; ++ + for (table_index = 0; table_index < count; table_index++) { +- if (((record->i2c_id & I2C_HW_CAP) == ( +- header->gpio_pin[table_index].gpio_id & +- I2C_HW_CAP)) && +- ((record->i2c_id & I2C_HW_ENGINE_ID_MASK) == +- (header->gpio_pin[table_index].gpio_id & +- I2C_HW_ENGINE_ID_MASK)) && +- ((record->i2c_id & I2C_HW_LANE_MUX) == +- (header->gpio_pin[table_index].gpio_id & +- I2C_HW_LANE_MUX))) { ++ if (((record->i2c_id & I2C_HW_CAP) == (pin->gpio_id & I2C_HW_CAP)) && ++ ((record->i2c_id & I2C_HW_ENGINE_ID_MASK) == (pin->gpio_id & I2C_HW_ENGINE_ID_MASK)) && ++ ((record->i2c_id & I2C_HW_LANE_MUX) == (pin->gpio_id & I2C_HW_LANE_MUX))) { + /* still valid */ + find_valid = true; + break; + } ++ pin = (struct atom_gpio_pin_assignment *)((uint8_t *)pin + sizeof(struct atom_gpio_pin_assignment)); + } + + /* If we don't find the entry that we are looking for then +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c +index 6f77d8e538ab1..9eb9fe5b8d2c5 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c +@@ -438,7 +438,7 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base, + } + + if (!new_clocks->dtbclk_en) { +- new_clocks->ref_dtbclk_khz = 0; ++ new_clocks->ref_dtbclk_khz = clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz * 1000; + } + + /* clock limits are received with MHz precision, divide by 1000 to prevent setting clocks at every call */ +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index 997ab031f816d..5260ad6de8038 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -1070,6 +1070,7 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) + int i, j; + struct dc_state *dangling_context = dc_create_state(dc); + struct dc_state *current_ctx; ++ struct pipe_ctx *pipe; + + if (dangling_context == NULL) + return; +@@ -1112,6 +1113,16 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) + } + + if (should_disable && old_stream) { ++ pipe = &dc->current_state->res_ctx.pipe_ctx[i]; ++ /* When disabling plane for a phantom pipe, we must turn on the ++ * phantom OTG so the disable programming gets the double buffer ++ * update. Otherwise the pipe will be left in a partially disabled ++ * state that can result in underflow or hang when enabling it ++ * again for different use. ++ */ ++ if (old_stream->mall_stream_config.type == SUBVP_PHANTOM) { ++ pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg); ++ } + dc_rem_all_planes_for_stream(dc, old_stream, dangling_context); + disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context); + +@@ -1760,6 +1771,12 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c + context->stream_count == 0) + dc->hwss.prepare_bandwidth(dc, context); + ++ /* When SubVP is active, all HW programming must be done while ++ * SubVP lock is acquired ++ */ ++ if (dc->hwss.subvp_pipe_control_lock) ++ dc->hwss.subvp_pipe_control_lock(dc, context, true, true, NULL, subvp_prev_use); ++ + if (dc->debug.enable_double_buffered_dsc_pg_support) + dc->hwss.update_dsc_pg(dc, context, false); + +@@ -1787,9 +1804,6 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c + dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe); + } + +- if (dc->hwss.subvp_pipe_control_lock) +- dc->hwss.subvp_pipe_control_lock(dc, context, true, true, NULL, subvp_prev_use); +- + result = dc->hwss.apply_ctx_to_hw(dc, context); + + if (result != DC_OK) { +@@ -3576,7 +3590,6 @@ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc, + + struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream); + bool force_minimal_pipe_splitting = false; +- uint32_t i; + + *is_plane_addition = false; + +@@ -3608,27 +3621,11 @@ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc, + } + } + +- /* For SubVP pipe split case when adding MPO video +- * we need to add a minimal transition. In this case +- * there will be 2 streams (1 main stream, 1 phantom +- * stream). ++ /* For SubVP when adding MPO video we need to add a minimal transition. + */ +- if (cur_stream_status && +- dc->current_state->stream_count == 2 && +- stream->mall_stream_config.type == SUBVP_MAIN) { +- bool is_pipe_split = false; +- +- for (i = 0; i < dc->res_pool->pipe_count; i++) { +- if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream && +- (dc->current_state->res_ctx.pipe_ctx[i].bottom_pipe || +- dc->current_state->res_ctx.pipe_ctx[i].next_odm_pipe)) { +- is_pipe_split = true; +- break; +- } +- } +- ++ if (cur_stream_status && stream->mall_stream_config.type == SUBVP_MAIN) { + /* determine if minimal transition is required due to SubVP*/ +- if (surface_count > 0 && is_pipe_split) { ++ if (surface_count > 0) { + if (cur_stream_status->plane_count > surface_count) { + force_minimal_pipe_splitting = true; + } else if (cur_stream_status->plane_count < surface_count) { +@@ -3650,10 +3647,32 @@ static bool commit_minimal_transition_state(struct dc *dc, + bool temp_subvp_policy; + enum dc_status ret = DC_ERROR_UNEXPECTED; + unsigned int i, j; ++ unsigned int pipe_in_use = 0; + + if (!transition_context) + return false; + ++ /* check current pipes in use*/ ++ for (i = 0; i < dc->res_pool->pipe_count; i++) { ++ struct pipe_ctx *pipe = &transition_base_context->res_ctx.pipe_ctx[i]; ++ ++ if (pipe->plane_state) ++ pipe_in_use++; ++ } ++ ++ /* When the OS add a new surface if we have been used all of pipes with odm combine ++ * and mpc split feature, it need use commit_minimal_transition_state to transition safely. ++ * After OS exit MPO, it will back to use odm and mpc split with all of pipes, we need ++ * call it again. Otherwise return true to skip. ++ * ++ * Reduce the scenarios to use dc_commit_state_no_check in the stage of flip. Especially ++ * enter/exit MPO when DCN still have enough resources. ++ */ ++ if (pipe_in_use != dc->res_pool->pipe_count) { ++ dc_release_state(transition_context); ++ return true; ++ } ++ + if (!dc->config.is_vmin_only_asic) { + tmp_mpc_policy = dc->debug.pipe_split_policy; + dc->debug.pipe_split_policy = MPC_SPLIT_AVOID; +diff --git a/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c +index fc6aa098bda06..8db9f75144662 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c +@@ -1128,6 +1128,7 @@ struct resource_pool *dce60_create_resource_pool( + if (dce60_construct(num_virtual_links, dc, pool)) + return &pool->base; + ++ kfree(pool); + BREAK_TO_DEBUGGER(); + return NULL; + } +@@ -1325,6 +1326,7 @@ struct resource_pool *dce61_create_resource_pool( + if (dce61_construct(num_virtual_links, dc, pool)) + return &pool->base; + ++ kfree(pool); + BREAK_TO_DEBUGGER(); + return NULL; + } +@@ -1518,6 +1520,7 @@ struct resource_pool *dce64_create_resource_pool( + if (dce64_construct(num_virtual_links, dc, pool)) + return &pool->base; + ++ kfree(pool); + BREAK_TO_DEBUGGER(); + return NULL; + } +diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +index b28025960050c..5825e6f412bd7 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +@@ -1137,6 +1137,7 @@ struct resource_pool *dce80_create_resource_pool( + if (dce80_construct(num_virtual_links, dc, pool)) + return &pool->base; + ++ kfree(pool); + BREAK_TO_DEBUGGER(); + return NULL; + } +@@ -1336,6 +1337,7 @@ struct resource_pool *dce81_create_resource_pool( + if (dce81_construct(num_virtual_links, dc, pool)) + return &pool->base; + ++ kfree(pool); + BREAK_TO_DEBUGGER(); + return NULL; + } +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 11e4c4e469473..c06538c37a11f 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 +@@ -867,6 +867,32 @@ static void false_optc_underflow_wa( + tg->funcs->clear_optc_underflow(tg); + } + ++static int calculate_vready_offset_for_group(struct pipe_ctx *pipe) ++{ ++ struct pipe_ctx *other_pipe; ++ int vready_offset = pipe->pipe_dlg_param.vready_offset; ++ ++ /* Always use the largest vready_offset of all connected pipes */ ++ for (other_pipe = pipe->bottom_pipe; other_pipe != NULL; other_pipe = other_pipe->bottom_pipe) { ++ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset) ++ vready_offset = other_pipe->pipe_dlg_param.vready_offset; ++ } ++ for (other_pipe = pipe->top_pipe; other_pipe != NULL; other_pipe = other_pipe->top_pipe) { ++ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset) ++ vready_offset = other_pipe->pipe_dlg_param.vready_offset; ++ } ++ for (other_pipe = pipe->next_odm_pipe; other_pipe != NULL; other_pipe = other_pipe->next_odm_pipe) { ++ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset) ++ vready_offset = other_pipe->pipe_dlg_param.vready_offset; ++ } ++ for (other_pipe = pipe->prev_odm_pipe; other_pipe != NULL; other_pipe = other_pipe->prev_odm_pipe) { ++ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset) ++ vready_offset = other_pipe->pipe_dlg_param.vready_offset; ++ } ++ ++ return vready_offset; ++} ++ + enum dc_status dcn10_enable_stream_timing( + struct pipe_ctx *pipe_ctx, + struct dc_state *context, +@@ -910,7 +936,7 @@ enum dc_status dcn10_enable_stream_timing( + pipe_ctx->stream_res.tg->funcs->program_timing( + pipe_ctx->stream_res.tg, + &stream->timing, +- pipe_ctx->pipe_dlg_param.vready_offset, ++ calculate_vready_offset_for_group(pipe_ctx), + pipe_ctx->pipe_dlg_param.vstartup_start, + pipe_ctx->pipe_dlg_param.vupdate_offset, + pipe_ctx->pipe_dlg_param.vupdate_width, +@@ -2900,7 +2926,7 @@ void dcn10_program_pipe( + + pipe_ctx->stream_res.tg->funcs->program_global_sync( + pipe_ctx->stream_res.tg, +- pipe_ctx->pipe_dlg_param.vready_offset, ++ calculate_vready_offset_for_group(pipe_ctx), + pipe_ctx->pipe_dlg_param.vstartup_start, + pipe_ctx->pipe_dlg_param.vupdate_offset, + pipe_ctx->pipe_dlg_param.vupdate_width); +diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +index a7e0001a8f46d..f348bc15a9256 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +@@ -1616,6 +1616,31 @@ static void dcn20_update_dchubp_dpp( + hubp->funcs->phantom_hubp_post_enable(hubp); + } + ++static int calculate_vready_offset_for_group(struct pipe_ctx *pipe) ++{ ++ struct pipe_ctx *other_pipe; ++ int vready_offset = pipe->pipe_dlg_param.vready_offset; ++ ++ /* Always use the largest vready_offset of all connected pipes */ ++ for (other_pipe = pipe->bottom_pipe; other_pipe != NULL; other_pipe = other_pipe->bottom_pipe) { ++ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset) ++ vready_offset = other_pipe->pipe_dlg_param.vready_offset; ++ } ++ for (other_pipe = pipe->top_pipe; other_pipe != NULL; other_pipe = other_pipe->top_pipe) { ++ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset) ++ vready_offset = other_pipe->pipe_dlg_param.vready_offset; ++ } ++ for (other_pipe = pipe->next_odm_pipe; other_pipe != NULL; other_pipe = other_pipe->next_odm_pipe) { ++ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset) ++ vready_offset = other_pipe->pipe_dlg_param.vready_offset; ++ } ++ for (other_pipe = pipe->prev_odm_pipe; other_pipe != NULL; other_pipe = other_pipe->prev_odm_pipe) { ++ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset) ++ vready_offset = other_pipe->pipe_dlg_param.vready_offset; ++ } ++ ++ return vready_offset; ++} + + static void dcn20_program_pipe( + struct dc *dc, +@@ -1634,16 +1659,14 @@ static void dcn20_program_pipe( + && !pipe_ctx->prev_odm_pipe) { + pipe_ctx->stream_res.tg->funcs->program_global_sync( + pipe_ctx->stream_res.tg, +- pipe_ctx->pipe_dlg_param.vready_offset, ++ calculate_vready_offset_for_group(pipe_ctx), + pipe_ctx->pipe_dlg_param.vstartup_start, + pipe_ctx->pipe_dlg_param.vupdate_offset, + pipe_ctx->pipe_dlg_param.vupdate_width); + + if (pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) { +- pipe_ctx->stream_res.tg->funcs->wait_for_state( +- pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK); +- pipe_ctx->stream_res.tg->funcs->wait_for_state( +- pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); ++ pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK); ++ pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); + } + + pipe_ctx->stream_res.tg->funcs->set_vtg_params( +@@ -2037,7 +2060,7 @@ bool dcn20_update_bandwidth( + + pipe_ctx->stream_res.tg->funcs->program_global_sync( + pipe_ctx->stream_res.tg, +- pipe_ctx->pipe_dlg_param.vready_offset, ++ calculate_vready_offset_for_group(pipe_ctx), + pipe_ctx->pipe_dlg_param.vstartup_start, + pipe_ctx->pipe_dlg_param.vupdate_offset, + pipe_ctx->pipe_dlg_param.vupdate_width); +diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c +index df4f251191424..e4472c6be6c32 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c +@@ -225,11 +225,7 @@ static void dccg32_set_dtbclk_dto( + } else { + REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst], + DTBCLK_DTO_ENABLE[params->otg_inst], 0, +- PIPE_DTO_SRC_SEL[params->otg_inst], 1); +- if (params->is_hdmi) +- REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst], +- PIPE_DTO_SRC_SEL[params->otg_inst], 0); +- ++ PIPE_DTO_SRC_SEL[params->otg_inst], params->is_hdmi ? 0 : 1); + REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0); + REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0); + } +diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +index d1598e3131f66..33ab6fdc36175 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +@@ -1901,7 +1901,7 @@ int dcn32_populate_dml_pipes_from_context( + + pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal; + if (context->stream_count == 1 && +- context->stream_status[0].plane_count <= 1 && ++ context->stream_status[0].plane_count == 1 && + !dc_is_hdmi_signal(res_ctx->pipe_ctx[i].stream->signal) && + is_h_timing_divisible_by_2(res_ctx->pipe_ctx[i].stream) && + pipe->stream->timing.pix_clk_100hz * 100 > DCN3_2_VMIN_DISPCLK_HZ && +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +index 2abe3967f7fbd..d1bf49d207de4 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +@@ -531,9 +531,11 @@ void dcn32_set_phantom_stream_timing(struct dc *dc, + unsigned int i, pipe_idx; + struct pipe_ctx *pipe; + uint32_t phantom_vactive, phantom_bp, pstate_width_fw_delay_lines; ++ unsigned int num_dpp; + unsigned int vlevel = context->bw_ctx.dml.vba.VoltageLevel; + unsigned int dcfclk = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb]; + unsigned int socclk = context->bw_ctx.dml.vba.SOCCLKPerState[vlevel]; ++ struct vba_vars_st *vba = &context->bw_ctx.dml.vba; + + dc_assert_fp_enabled(); + +@@ -569,6 +571,11 @@ void dcn32_set_phantom_stream_timing(struct dc *dc, + phantom_vactive = get_subviewport_lines_needed_in_mall(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx) + + pstate_width_fw_delay_lines + dc->caps.subvp_swath_height_margin_lines; + ++ // W/A for DCC corruption with certain high resolution timings. ++ // Determing if pipesplit is used. If so, add meta_row_height to the phantom vactive. ++ num_dpp = vba->NoOfDPP[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]]; ++ phantom_vactive += num_dpp > 1 ? vba->meta_row_height[vba->pipe_plane[pipe_idx]] : 0; ++ + // For backporch of phantom pipe, use vstartup of the main pipe + phantom_bp = get_vstartup(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); + +diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h +index a40ead44778af..d18162e9ed1da 100644 +--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h ++++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h +@@ -354,7 +354,8 @@ struct amd_pm_funcs { + int (*get_power_profile_mode)(void *handle, char *buf); + int (*set_power_profile_mode)(void *handle, long *input, uint32_t size); + int (*set_fine_grain_clk_vol)(void *handle, uint32_t type, long *input, uint32_t size); +- int (*odn_edit_dpm_table)(void *handle, uint32_t type, long *input, uint32_t size); ++ int (*odn_edit_dpm_table)(void *handle, enum PP_OD_DPM_TABLE_COMMAND type, ++ long *input, uint32_t size); + int (*set_mp1_state)(void *handle, enum pp_mp1_state mp1_state); + int (*smu_i2c_bus_access)(void *handle, bool acquire); + int (*gfx_state_change_set)(void *handle, uint32_t state); +diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +index ec055858eb95a..1159ae114dd02 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c ++++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +@@ -838,7 +838,8 @@ static int pp_set_fine_grain_clk_vol(void *handle, uint32_t type, long *input, u + return hwmgr->hwmgr_func->set_fine_grain_clk_vol(hwmgr, type, input, size); + } + +-static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint32_t size) ++static int pp_odn_edit_dpm_table(void *handle, enum PP_OD_DPM_TABLE_COMMAND type, ++ long *input, uint32_t size) + { + struct pp_hwmgr *hwmgr = handle; + +diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c +index 67d7da0b6fed5..1d829402cd2e2 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c ++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c +@@ -75,8 +75,10 @@ int psm_init_power_state_table(struct pp_hwmgr *hwmgr) + for (i = 0; i < table_entries; i++) { + result = hwmgr->hwmgr_func->get_pp_table_entry(hwmgr, i, state); + if (result) { ++ kfree(hwmgr->current_ps); + kfree(hwmgr->request_ps); + kfree(hwmgr->ps); ++ hwmgr->current_ps = NULL; + hwmgr->request_ps = NULL; + hwmgr->ps = NULL; + return -EINVAL; +diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c +index 190af79f3236f..dad3e3741a4e8 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c ++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c +@@ -67,21 +67,22 @@ int vega10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, + int vega10_fan_ctrl_get_fan_speed_pwm(struct pp_hwmgr *hwmgr, + uint32_t *speed) + { +- struct amdgpu_device *adev = hwmgr->adev; +- uint32_t duty100, duty; +- uint64_t tmp64; ++ uint32_t current_rpm; ++ uint32_t percent = 0; + +- duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1), +- CG_FDO_CTRL1, FMAX_DUTY100); +- duty = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_THERMAL_STATUS), +- CG_THERMAL_STATUS, FDO_PWM_DUTY); ++ if (hwmgr->thermal_controller.fanInfo.bNoFan) ++ return 0; + +- if (!duty100) +- return -EINVAL; ++ if (vega10_get_current_rpm(hwmgr, ¤t_rpm)) ++ return -1; ++ ++ if (hwmgr->thermal_controller. ++ advanceFanControlParameters.usMaxFanRPM != 0) ++ percent = current_rpm * 255 / ++ hwmgr->thermal_controller. ++ advanceFanControlParameters.usMaxFanRPM; + +- tmp64 = (uint64_t)duty * 255; +- do_div(tmp64, duty100); +- *speed = MIN((uint32_t)tmp64, 255); ++ *speed = MIN(percent, 255); + + return 0; + } +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 97b3ad3690467..b30684c84e20e 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c ++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c +@@ -2961,7 +2961,8 @@ static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr, + data->od8_settings.od8_settings_array; + OverDriveTable_t *od_table = + &(data->smc_state_table.overdrive_table); +- int32_t input_index, input_clk, input_vol, i; ++ int32_t input_clk, input_vol, i; ++ uint32_t input_index; + int od8_id; + int ret; + +diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +index 70b560737687e..ad5f6a15a1d7d 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +@@ -1588,6 +1588,10 @@ bool smu_v11_0_baco_is_support(struct smu_context *smu) + if (amdgpu_sriov_vf(smu->adev) || !smu_baco->platform_support) + return false; + ++ /* return true if ASIC is in BACO state already */ ++ if (smu_v11_0_baco_get_state(smu) == SMU_BACO_STATE_ENTER) ++ return true; ++ + /* Arcturus does not support this bit mask */ + if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_BACO_BIT) && + !smu_cmn_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT)) +diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +index d74debc584f89..39deb06a86ba3 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +@@ -1436,7 +1436,7 @@ static int smu_v13_0_7_get_power_limit(struct smu_context *smu, + + static int smu_v13_0_7_get_power_profile_mode(struct smu_context *smu, char *buf) + { +- DpmActivityMonitorCoeffIntExternal_t activity_monitor_external[PP_SMC_POWER_PROFILE_COUNT]; ++ DpmActivityMonitorCoeffIntExternal_t *activity_monitor_external; + uint32_t i, j, size = 0; + int16_t workload_type = 0; + int result = 0; +@@ -1444,6 +1444,12 @@ static int smu_v13_0_7_get_power_profile_mode(struct smu_context *smu, char *buf + if (!buf) + return -EINVAL; + ++ activity_monitor_external = kcalloc(PP_SMC_POWER_PROFILE_COUNT, ++ sizeof(*activity_monitor_external), ++ GFP_KERNEL); ++ if (!activity_monitor_external) ++ return -ENOMEM; ++ + size += sysfs_emit_at(buf, size, " "); + for (i = 0; i <= PP_SMC_POWER_PROFILE_WINDOW3D; i++) + size += sysfs_emit_at(buf, size, "%-14s%s", amdgpu_pp_profile_name[i], +@@ -1456,15 +1462,17 @@ static int smu_v13_0_7_get_power_profile_mode(struct smu_context *smu, char *buf + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + i); +- if (workload_type < 0) +- return -EINVAL; ++ if (workload_type < 0) { ++ result = -EINVAL; ++ goto out; ++ } + + result = smu_cmn_update_table(smu, + SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type, + (void *)(&activity_monitor_external[i]), false); + if (result) { + dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); +- return result; ++ goto out; + } + } + +@@ -1492,7 +1500,10 @@ do { \ + PRINT_DPM_MONITOR(Fclk_BoosterFreq); + #undef PRINT_DPM_MONITOR + +- return size; ++ result = size; ++out: ++ kfree(activity_monitor_external); ++ return result; + } + + static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size) +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h +index 94de73cbeb2dd..17445800248dd 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511.h ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h +@@ -402,7 +402,8 @@ static inline int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511) + + void adv7533_dsi_power_on(struct adv7511 *adv); + void adv7533_dsi_power_off(struct adv7511 *adv); +-void adv7533_mode_set(struct adv7511 *adv, const struct drm_display_mode *mode); ++enum drm_mode_status adv7533_mode_valid(struct adv7511 *adv, ++ const struct drm_display_mode *mode); + int adv7533_patch_registers(struct adv7511 *adv); + int adv7533_patch_cec_registers(struct adv7511 *adv); + int adv7533_attach_dsi(struct adv7511 *adv); +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +index f887200e8abc9..78b72739e5c3e 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +@@ -697,7 +697,7 @@ adv7511_detect(struct adv7511 *adv7511, struct drm_connector *connector) + } + + static enum drm_mode_status adv7511_mode_valid(struct adv7511 *adv7511, +- struct drm_display_mode *mode) ++ const struct drm_display_mode *mode) + { + if (mode->clock > 165000) + return MODE_CLOCK_HIGH; +@@ -791,9 +791,6 @@ static void adv7511_mode_set(struct adv7511 *adv7511, + regmap_update_bits(adv7511->regmap, 0x17, + 0x60, (vsync_polarity << 6) | (hsync_polarity << 5)); + +- if (adv7511->type == ADV7533 || adv7511->type == ADV7535) +- adv7533_mode_set(adv7511, adj_mode); +- + drm_mode_copy(&adv7511->curr_mode, adj_mode); + + /* +@@ -913,6 +910,18 @@ static void adv7511_bridge_mode_set(struct drm_bridge *bridge, + adv7511_mode_set(adv, mode, adj_mode); + } + ++static enum drm_mode_status adv7511_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, ++ const struct drm_display_mode *mode) ++{ ++ struct adv7511 *adv = bridge_to_adv7511(bridge); ++ ++ if (adv->type == ADV7533 || adv->type == ADV7535) ++ return adv7533_mode_valid(adv, mode); ++ else ++ return adv7511_mode_valid(adv, mode); ++} ++ + static int adv7511_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) + { +@@ -960,6 +969,7 @@ static const struct drm_bridge_funcs adv7511_bridge_funcs = { + .enable = adv7511_bridge_enable, + .disable = adv7511_bridge_disable, + .mode_set = adv7511_bridge_mode_set, ++ .mode_valid = adv7511_bridge_mode_valid, + .attach = adv7511_bridge_attach, + .detect = adv7511_bridge_detect, + .get_edid = adv7511_bridge_get_edid, +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7533.c b/drivers/gpu/drm/bridge/adv7511/adv7533.c +index ef6270806d1d3..258c79d4dab0a 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7533.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7533.c +@@ -100,26 +100,27 @@ void adv7533_dsi_power_off(struct adv7511 *adv) + regmap_write(adv->regmap_cec, 0x27, 0x0b); + } + +-void adv7533_mode_set(struct adv7511 *adv, const struct drm_display_mode *mode) ++enum drm_mode_status adv7533_mode_valid(struct adv7511 *adv, ++ const struct drm_display_mode *mode) + { ++ int lanes; + struct mipi_dsi_device *dsi = adv->dsi; +- int lanes, ret; +- +- if (adv->num_dsi_lanes != 4) +- return; + + if (mode->clock > 80000) + lanes = 4; + else + lanes = 3; + +- if (lanes != dsi->lanes) { +- mipi_dsi_detach(dsi); +- dsi->lanes = lanes; +- ret = mipi_dsi_attach(dsi); +- if (ret) +- dev_err(&dsi->dev, "failed to change host lanes\n"); +- } ++ /* ++ * TODO: add support for dynamic switching of lanes ++ * by using the bridge pre_enable() op . Till then filter ++ * out the modes which shall need different number of lanes ++ * than what was configured in the device tree. ++ */ ++ if (lanes != dsi->lanes) ++ return MODE_BAD; ++ ++ return MODE_OK; + } + + int adv7533_patch_registers(struct adv7511 *adv) +diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c +index dfe4351c9bdd3..99123eec45511 100644 +--- a/drivers/gpu/drm/bridge/ite-it6505.c ++++ b/drivers/gpu/drm/bridge/ite-it6505.c +@@ -2860,10 +2860,7 @@ static int it6505_bridge_attach(struct drm_bridge *bridge, + } + + /* Register aux channel */ +- it6505->aux.name = "DP-AUX"; +- it6505->aux.dev = dev; + it6505->aux.drm_dev = bridge->dev; +- it6505->aux.transfer = it6505_aux_transfer; + + ret = drm_dp_aux_register(&it6505->aux); + +@@ -3316,6 +3313,11 @@ static int it6505_i2c_probe(struct i2c_client *client, + DRM_DEV_DEBUG_DRIVER(dev, "it6505 device name: %s", dev_name(dev)); + debugfs_init(it6505); + ++ it6505->aux.name = "DP-AUX"; ++ it6505->aux.dev = dev; ++ it6505->aux.transfer = it6505_aux_transfer; ++ drm_dp_aux_init(&it6505->aux); ++ + it6505->bridge.funcs = &it6505_bridge_funcs; + it6505->bridge.type = DRM_MODE_CONNECTOR_DisplayPort; + it6505->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | +diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c +index 98cc3137c0625..02b4a7dc92f5e 100644 +--- a/drivers/gpu/drm/drm_atomic_helper.c ++++ b/drivers/gpu/drm/drm_atomic_helper.c +@@ -945,7 +945,6 @@ int drm_atomic_helper_check_crtc_state(struct drm_crtc_state *crtc_state, + bool can_disable_primary_planes) + { + struct drm_device *dev = crtc_state->crtc->dev; +- struct drm_atomic_state *state = crtc_state->state; + + if (!crtc_state->enable) + return 0; +@@ -956,14 +955,7 @@ int drm_atomic_helper_check_crtc_state(struct drm_crtc_state *crtc_state, + struct drm_plane *plane; + + drm_for_each_plane_mask(plane, dev, crtc_state->plane_mask) { +- struct drm_plane_state *plane_state; +- +- if (plane->type != DRM_PLANE_TYPE_PRIMARY) +- continue; +- plane_state = drm_atomic_get_plane_state(state, plane); +- if (IS_ERR(plane_state)) +- return PTR_ERR(plane_state); +- if (plane_state->fb && plane_state->crtc) { ++ if (plane->type == DRM_PLANE_TYPE_PRIMARY) { + has_primary_plane = true; + break; + } +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index 4005dab6147d9..b36abfa915813 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -87,6 +87,8 @@ static int oui(u8 first, u8 second, u8 third) + #define EDID_QUIRK_FORCE_10BPC (1 << 11) + /* Non desktop display (i.e. HMD) */ + #define EDID_QUIRK_NON_DESKTOP (1 << 12) ++/* Cap the DSC target bitrate to 15bpp */ ++#define EDID_QUIRK_CAP_DSC_15BPP (1 << 13) + + #define MICROSOFT_IEEE_OUI 0xca125c + +@@ -147,6 +149,12 @@ static const struct edid_quirk { + EDID_QUIRK('F', 'C', 'M', 13600, EDID_QUIRK_PREFER_LARGE_75 | + EDID_QUIRK_DETAILED_IN_CM), + ++ /* LG 27GP950 */ ++ EDID_QUIRK('G', 'S', 'M', 0x5bbf, EDID_QUIRK_CAP_DSC_15BPP), ++ ++ /* LG 27GN950 */ ++ EDID_QUIRK('G', 'S', 'M', 0x5b9a, EDID_QUIRK_CAP_DSC_15BPP), ++ + /* LGD panel of HP zBook 17 G2, eDP 10 bpc, but reports unknown bpc */ + EDID_QUIRK('L', 'G', 'D', 764, EDID_QUIRK_FORCE_10BPC), + +@@ -6166,6 +6174,7 @@ static void drm_reset_display_info(struct drm_connector *connector) + + info->mso_stream_count = 0; + info->mso_pixel_overlap = 0; ++ info->max_dsc_bpp = 0; + } + + static u32 update_display_info(struct drm_connector *connector, +@@ -6252,6 +6261,9 @@ out: + info->non_desktop = true; + } + ++ if (quirks & EDID_QUIRK_CAP_DSC_15BPP) ++ info->max_dsc_bpp = 15; ++ + return quirks; + } + +diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c +index e09331bb3bc73..6242dfbe92402 100644 +--- a/drivers/gpu/drm/drm_fourcc.c ++++ b/drivers/gpu/drm/drm_fourcc.c +@@ -297,12 +297,12 @@ const struct drm_format_info *__drm_format_info(u32 format) + .vsub = 2, .is_yuv = true }, + { .format = DRM_FORMAT_Q410, .depth = 0, + .num_planes = 3, .char_per_block = { 2, 2, 2 }, +- .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 0, +- .vsub = 0, .is_yuv = true }, ++ .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 1, ++ .vsub = 1, .is_yuv = true }, + { .format = DRM_FORMAT_Q401, .depth = 0, + .num_planes = 3, .char_per_block = { 2, 2, 2 }, +- .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 0, +- .vsub = 0, .is_yuv = true }, ++ .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 1, ++ .vsub = 1, .is_yuv = true }, + { .format = DRM_FORMAT_P030, .depth = 0, .num_planes = 2, + .char_per_block = { 4, 8, 0 }, .block_w = { 3, 3, 0 }, .block_h = { 1, 1, 0 }, + .hsub = 2, .vsub = 2, .is_yuv = true}, +diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +index 37018bc55810d..f667e7906d1f4 100644 +--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c ++++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +@@ -416,6 +416,12 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu) + if (gpu->identity.model == chipModel_GC700) + gpu->identity.features &= ~chipFeatures_FAST_CLEAR; + ++ /* These models/revisions don't have the 2D pipe bit */ ++ if ((gpu->identity.model == chipModel_GC500 && ++ gpu->identity.revision <= 2) || ++ gpu->identity.model == chipModel_GC300) ++ gpu->identity.features |= chipFeatures_PIPE_2D; ++ + if ((gpu->identity.model == chipModel_GC500 && + gpu->identity.revision < 2) || + (gpu->identity.model == chipModel_GC300 && +@@ -449,8 +455,9 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu) + gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_5); + } + +- /* GC600 idle register reports zero bits where modules aren't present */ +- if (gpu->identity.model == chipModel_GC600) ++ /* GC600/300 idle register reports zero bits where modules aren't present */ ++ if (gpu->identity.model == chipModel_GC600 || ++ gpu->identity.model == chipModel_GC300) + gpu->idle_mask = VIVS_HI_IDLE_STATE_TX | + VIVS_HI_IDLE_STATE_RA | + VIVS_HI_IDLE_STATE_SE | +diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c +index 4d4a715b429d1..2c2b92324a2e9 100644 +--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c ++++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c +@@ -60,8 +60,9 @@ static int fsl_dcu_drm_connector_get_modes(struct drm_connector *connector) + return drm_panel_get_modes(fsl_connector->panel, connector); + } + +-static int fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector, +- struct drm_display_mode *mode) ++static enum drm_mode_status ++fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) + { + if (mode->hdisplay & 0xf) + return MODE_ERROR; +diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c +index 28bdb936cd1fc..edbdb949b6ced 100644 +--- a/drivers/gpu/drm/i915/display/intel_bios.c ++++ b/drivers/gpu/drm/i915/display/intel_bios.c +@@ -414,7 +414,7 @@ static void *generate_lfp_data_ptrs(struct drm_i915_private *i915, + ptrs->lvds_entries++; + + if (size != 0 || ptrs->lvds_entries != 3) { +- kfree(ptrs); ++ kfree(ptrs_block); + return NULL; + } + +diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c +index 2b5bc95a8b0df..78b3427471bd7 100644 +--- a/drivers/gpu/drm/i915/display/intel_dp.c ++++ b/drivers/gpu/drm/i915/display/intel_dp.c +@@ -3675,61 +3675,6 @@ static void intel_dp_phy_pattern_update(struct intel_dp *intel_dp, + } + } + +-static void +-intel_dp_autotest_phy_ddi_disable(struct intel_dp *intel_dp, +- const struct intel_crtc_state *crtc_state) +-{ +- struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); +- struct drm_device *dev = dig_port->base.base.dev; +- struct drm_i915_private *dev_priv = to_i915(dev); +- struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc); +- enum pipe pipe = crtc->pipe; +- u32 trans_ddi_func_ctl_value, trans_conf_value, dp_tp_ctl_value; +- +- trans_ddi_func_ctl_value = intel_de_read(dev_priv, +- TRANS_DDI_FUNC_CTL(pipe)); +- trans_conf_value = intel_de_read(dev_priv, PIPECONF(pipe)); +- dp_tp_ctl_value = intel_de_read(dev_priv, TGL_DP_TP_CTL(pipe)); +- +- trans_ddi_func_ctl_value &= ~(TRANS_DDI_FUNC_ENABLE | +- TGL_TRANS_DDI_PORT_MASK); +- trans_conf_value &= ~PIPECONF_ENABLE; +- dp_tp_ctl_value &= ~DP_TP_CTL_ENABLE; +- +- intel_de_write(dev_priv, PIPECONF(pipe), trans_conf_value); +- intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(pipe), +- trans_ddi_func_ctl_value); +- intel_de_write(dev_priv, TGL_DP_TP_CTL(pipe), dp_tp_ctl_value); +-} +- +-static void +-intel_dp_autotest_phy_ddi_enable(struct intel_dp *intel_dp, +- const struct intel_crtc_state *crtc_state) +-{ +- struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); +- struct drm_device *dev = dig_port->base.base.dev; +- struct drm_i915_private *dev_priv = to_i915(dev); +- enum port port = dig_port->base.port; +- struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc); +- enum pipe pipe = crtc->pipe; +- u32 trans_ddi_func_ctl_value, trans_conf_value, dp_tp_ctl_value; +- +- trans_ddi_func_ctl_value = intel_de_read(dev_priv, +- TRANS_DDI_FUNC_CTL(pipe)); +- trans_conf_value = intel_de_read(dev_priv, PIPECONF(pipe)); +- dp_tp_ctl_value = intel_de_read(dev_priv, TGL_DP_TP_CTL(pipe)); +- +- trans_ddi_func_ctl_value |= TRANS_DDI_FUNC_ENABLE | +- TGL_TRANS_DDI_SELECT_PORT(port); +- trans_conf_value |= PIPECONF_ENABLE; +- dp_tp_ctl_value |= DP_TP_CTL_ENABLE; +- +- intel_de_write(dev_priv, PIPECONF(pipe), trans_conf_value); +- intel_de_write(dev_priv, TGL_DP_TP_CTL(pipe), dp_tp_ctl_value); +- intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(pipe), +- trans_ddi_func_ctl_value); +-} +- + static void intel_dp_process_phy_request(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) + { +@@ -3748,14 +3693,10 @@ static void intel_dp_process_phy_request(struct intel_dp *intel_dp, + intel_dp_get_adjust_train(intel_dp, crtc_state, DP_PHY_DPRX, + link_status); + +- intel_dp_autotest_phy_ddi_disable(intel_dp, crtc_state); +- + intel_dp_set_signal_levels(intel_dp, crtc_state, DP_PHY_DPRX); + + intel_dp_phy_pattern_update(intel_dp, crtc_state); + +- intel_dp_autotest_phy_ddi_enable(intel_dp, crtc_state); +- + drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET, + intel_dp->train_set, crtc_state->lane_count); + +diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c +index 73d9eda1d6b7a..e63329bc80659 100644 +--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c ++++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c +@@ -413,7 +413,7 @@ retry: + vma->mmo = mmo; + + if (CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND) +- intel_wakeref_auto(&to_gt(i915)->userfault_wakeref, ++ intel_wakeref_auto(&i915->runtime_pm.userfault_wakeref, + msecs_to_jiffies_timeout(CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND)); + + if (write) { +@@ -557,11 +557,13 @@ void i915_gem_object_runtime_pm_release_mmap_offset(struct drm_i915_gem_object * + + drm_vma_node_unmap(&bo->base.vma_node, bdev->dev_mapping); + +- if (obj->userfault_count) { +- /* rpm wakeref provide exclusive access */ +- list_del(&obj->userfault_link); +- obj->userfault_count = 0; +- } ++ /* ++ * We have exclusive access here via runtime suspend. All other callers ++ * must first grab the rpm wakeref. ++ */ ++ GEM_BUG_ON(!obj->userfault_count); ++ list_del(&obj->userfault_link); ++ obj->userfault_count = 0; + } + + void i915_gem_object_release_mmap_offset(struct drm_i915_gem_object *obj) +@@ -587,13 +589,6 @@ void i915_gem_object_release_mmap_offset(struct drm_i915_gem_object *obj) + spin_lock(&obj->mmo.lock); + } + spin_unlock(&obj->mmo.lock); +- +- if (obj->userfault_count) { +- mutex_lock(&to_gt(to_i915(obj->base.dev))->lmem_userfault_lock); +- list_del(&obj->userfault_link); +- mutex_unlock(&to_gt(to_i915(obj->base.dev))->lmem_userfault_lock); +- obj->userfault_count = 0; +- } + } + + static struct i915_mmap_offset * +diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pm.c b/drivers/gpu/drm/i915/gem/i915_gem_pm.c +index 3428f735e786c..8d30db5e678c4 100644 +--- a/drivers/gpu/drm/i915/gem/i915_gem_pm.c ++++ b/drivers/gpu/drm/i915/gem/i915_gem_pm.c +@@ -24,7 +24,7 @@ void i915_gem_suspend(struct drm_i915_private *i915) + { + GEM_TRACE("%s\n", dev_name(i915->drm.dev)); + +- intel_wakeref_auto(&to_gt(i915)->userfault_wakeref, 0); ++ intel_wakeref_auto(&i915->runtime_pm.userfault_wakeref, 0); + flush_workqueue(i915->wq); + + /* +diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +index 0d6d640225fc8..be4c081e7e13d 100644 +--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c ++++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +@@ -279,7 +279,7 @@ static struct ttm_tt *i915_ttm_tt_create(struct ttm_buffer_object *bo, + struct i915_ttm_tt *i915_tt; + int ret; + +- if (!obj) ++ if (i915_ttm_is_ghost_object(bo)) + return NULL; + + i915_tt = kzalloc(sizeof(*i915_tt), GFP_KERNEL); +@@ -362,7 +362,7 @@ static bool i915_ttm_eviction_valuable(struct ttm_buffer_object *bo, + { + struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo); + +- if (!obj) ++ if (i915_ttm_is_ghost_object(bo)) + return false; + + /* +@@ -509,18 +509,9 @@ static int i915_ttm_shrink(struct drm_i915_gem_object *obj, unsigned int flags) + static void i915_ttm_delete_mem_notify(struct ttm_buffer_object *bo) + { + struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo); +- intel_wakeref_t wakeref = 0; +- +- if (bo->resource && likely(obj)) { +- /* ttm_bo_release() already has dma_resv_lock */ +- if (i915_ttm_cpu_maps_iomem(bo->resource)) +- wakeref = intel_runtime_pm_get(&to_i915(obj->base.dev)->runtime_pm); + ++ if (bo->resource && !i915_ttm_is_ghost_object(bo)) { + __i915_gem_object_pages_fini(obj); +- +- if (wakeref) +- intel_runtime_pm_put(&to_i915(obj->base.dev)->runtime_pm, wakeref); +- + i915_ttm_free_cached_io_rsgt(obj); + } + } +@@ -628,7 +619,7 @@ static void i915_ttm_swap_notify(struct ttm_buffer_object *bo) + struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo); + int ret; + +- if (!obj) ++ if (i915_ttm_is_ghost_object(bo)) + return; + + ret = i915_ttm_move_notify(bo); +@@ -661,7 +652,7 @@ static int i915_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource + struct drm_i915_gem_object *obj = i915_ttm_to_gem(mem->bo); + bool unknown_state; + +- if (!obj) ++ if (i915_ttm_is_ghost_object(mem->bo)) + return -EINVAL; + + if (!kref_get_unless_zero(&obj->base.refcount)) +@@ -694,7 +685,7 @@ static unsigned long i915_ttm_io_mem_pfn(struct ttm_buffer_object *bo, + unsigned long base; + unsigned int ofs; + +- GEM_BUG_ON(!obj); ++ GEM_BUG_ON(i915_ttm_is_ghost_object(bo)); + GEM_WARN_ON(bo->ttm); + + base = obj->mm.region->iomap.base - obj->mm.region->region.start; +@@ -994,13 +985,12 @@ static vm_fault_t vm_fault_ttm(struct vm_fault *vmf) + struct vm_area_struct *area = vmf->vma; + struct ttm_buffer_object *bo = area->vm_private_data; + struct drm_device *dev = bo->base.dev; +- struct drm_i915_gem_object *obj; ++ struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo); + intel_wakeref_t wakeref = 0; + vm_fault_t ret; + int idx; + +- obj = i915_ttm_to_gem(bo); +- if (!obj) ++ if (i915_ttm_is_ghost_object(bo)) + return VM_FAULT_SIGBUS; + + /* Sanity check that we allow writing into this object */ +@@ -1057,16 +1047,19 @@ static vm_fault_t vm_fault_ttm(struct vm_fault *vmf) + if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) + goto out_rpm; + +- /* ttm_bo_vm_reserve() already has dma_resv_lock */ ++ /* ++ * ttm_bo_vm_reserve() already has dma_resv_lock. ++ * userfault_count is protected by dma_resv lock and rpm wakeref. ++ */ + if (ret == VM_FAULT_NOPAGE && wakeref && !obj->userfault_count) { + obj->userfault_count = 1; +- mutex_lock(&to_gt(to_i915(obj->base.dev))->lmem_userfault_lock); +- list_add(&obj->userfault_link, &to_gt(to_i915(obj->base.dev))->lmem_userfault_list); +- mutex_unlock(&to_gt(to_i915(obj->base.dev))->lmem_userfault_lock); ++ spin_lock(&to_i915(obj->base.dev)->runtime_pm.lmem_userfault_lock); ++ list_add(&obj->userfault_link, &to_i915(obj->base.dev)->runtime_pm.lmem_userfault_list); ++ spin_unlock(&to_i915(obj->base.dev)->runtime_pm.lmem_userfault_lock); + } + + if (wakeref & CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND) +- intel_wakeref_auto(&to_gt(to_i915(obj->base.dev))->userfault_wakeref, ++ intel_wakeref_auto(&to_i915(obj->base.dev)->runtime_pm.userfault_wakeref, + msecs_to_jiffies_timeout(CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND)); + + i915_ttm_adjust_lru(obj); +@@ -1098,7 +1091,7 @@ static void ttm_vm_open(struct vm_area_struct *vma) + struct drm_i915_gem_object *obj = + i915_ttm_to_gem(vma->vm_private_data); + +- GEM_BUG_ON(!obj); ++ GEM_BUG_ON(i915_ttm_is_ghost_object(vma->vm_private_data)); + i915_gem_object_get(obj); + } + +@@ -1107,7 +1100,7 @@ static void ttm_vm_close(struct vm_area_struct *vma) + struct drm_i915_gem_object *obj = + i915_ttm_to_gem(vma->vm_private_data); + +- GEM_BUG_ON(!obj); ++ GEM_BUG_ON(i915_ttm_is_ghost_object(vma->vm_private_data)); + i915_gem_object_put(obj); + } + +@@ -1128,7 +1121,27 @@ static u64 i915_ttm_mmap_offset(struct drm_i915_gem_object *obj) + + static void i915_ttm_unmap_virtual(struct drm_i915_gem_object *obj) + { ++ struct ttm_buffer_object *bo = i915_gem_to_ttm(obj); ++ intel_wakeref_t wakeref = 0; ++ ++ assert_object_held_shared(obj); ++ ++ if (i915_ttm_cpu_maps_iomem(bo->resource)) { ++ wakeref = intel_runtime_pm_get(&to_i915(obj->base.dev)->runtime_pm); ++ ++ /* userfault_count is protected by obj lock and rpm wakeref. */ ++ if (obj->userfault_count) { ++ spin_lock(&to_i915(obj->base.dev)->runtime_pm.lmem_userfault_lock); ++ list_del(&obj->userfault_link); ++ spin_unlock(&to_i915(obj->base.dev)->runtime_pm.lmem_userfault_lock); ++ obj->userfault_count = 0; ++ } ++ } ++ + ttm_bo_unmap_virtual(i915_gem_to_ttm(obj)); ++ ++ if (wakeref) ++ intel_runtime_pm_put(&to_i915(obj->base.dev)->runtime_pm, wakeref); + } + + static const struct drm_i915_gem_object_ops i915_gem_ttm_obj_ops = { +diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h +index e4842b4296fc2..2a94a99ef76b4 100644 +--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h ++++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h +@@ -27,19 +27,27 @@ i915_gem_to_ttm(struct drm_i915_gem_object *obj) + */ + void i915_ttm_bo_destroy(struct ttm_buffer_object *bo); + ++/** ++ * i915_ttm_is_ghost_object - Check if the ttm bo is a ghost object. ++ * @bo: Pointer to the ttm buffer object ++ * ++ * Return: True if the ttm bo is not a i915 object but a ghost ttm object, ++ * False otherwise. ++ */ ++static inline bool i915_ttm_is_ghost_object(struct ttm_buffer_object *bo) ++{ ++ return bo->destroy != i915_ttm_bo_destroy; ++} ++ + /** + * i915_ttm_to_gem - Convert a struct ttm_buffer_object to an embedding + * struct drm_i915_gem_object. + * +- * Return: Pointer to the embedding struct ttm_buffer_object, or NULL +- * if the object was not an i915 ttm object. ++ * Return: Pointer to the embedding struct ttm_buffer_object. + */ + static inline struct drm_i915_gem_object * + i915_ttm_to_gem(struct ttm_buffer_object *bo) + { +- if (bo->destroy != i915_ttm_bo_destroy) +- return NULL; +- + return container_of(bo, struct drm_i915_gem_object, __do_not_access); + } + +diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c +index 9a7e50534b84b..f59f812dc6d29 100644 +--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c ++++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c +@@ -560,7 +560,7 @@ int i915_ttm_move(struct ttm_buffer_object *bo, bool evict, + bool clear; + int ret; + +- if (GEM_WARN_ON(!obj)) { ++ if (GEM_WARN_ON(i915_ttm_is_ghost_object(bo))) { + ttm_bo_move_null(bo, dst_mem); + return 0; + } +diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h +index 04e435bce79bd..cbc8b857d5f7a 100644 +--- a/drivers/gpu/drm/i915/gt/intel_engine.h ++++ b/drivers/gpu/drm/i915/gt/intel_engine.h +@@ -348,4 +348,10 @@ intel_engine_get_hung_context(struct intel_engine_cs *engine) + return engine->hung_ce; + } + ++u64 intel_clamp_heartbeat_interval_ms(struct intel_engine_cs *engine, u64 value); ++u64 intel_clamp_max_busywait_duration_ns(struct intel_engine_cs *engine, u64 value); ++u64 intel_clamp_preempt_timeout_ms(struct intel_engine_cs *engine, u64 value); ++u64 intel_clamp_stop_timeout_ms(struct intel_engine_cs *engine, u64 value); ++u64 intel_clamp_timeslice_duration_ms(struct intel_engine_cs *engine, u64 value); ++ + #endif /* _INTEL_RINGBUFFER_H_ */ +diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c +index 1f7188129cd1f..83bfeb872bdaa 100644 +--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c ++++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c +@@ -486,6 +486,17 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id, + engine->logical_mask = BIT(logical_instance); + __sprint_engine_name(engine); + ++ if ((engine->class == COMPUTE_CLASS && !RCS_MASK(engine->gt) && ++ __ffs(CCS_MASK(engine->gt)) == engine->instance) || ++ engine->class == RENDER_CLASS) ++ engine->flags |= I915_ENGINE_FIRST_RENDER_COMPUTE; ++ ++ /* features common between engines sharing EUs */ ++ if (engine->class == RENDER_CLASS || engine->class == COMPUTE_CLASS) { ++ engine->flags |= I915_ENGINE_HAS_RCS_REG_STATE; ++ engine->flags |= I915_ENGINE_HAS_EU_PRIORITY; ++ } ++ + engine->props.heartbeat_interval_ms = + CONFIG_DRM_I915_HEARTBEAT_INTERVAL; + engine->props.max_busywait_duration_ns = +@@ -498,19 +509,28 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id, + CONFIG_DRM_I915_TIMESLICE_DURATION; + + /* Override to uninterruptible for OpenCL workloads. */ +- if (GRAPHICS_VER(i915) == 12 && engine->class == RENDER_CLASS) ++ if (GRAPHICS_VER(i915) == 12 && (engine->flags & I915_ENGINE_HAS_RCS_REG_STATE)) + engine->props.preempt_timeout_ms = 0; + +- if ((engine->class == COMPUTE_CLASS && !RCS_MASK(engine->gt) && +- __ffs(CCS_MASK(engine->gt)) == engine->instance) || +- engine->class == RENDER_CLASS) +- engine->flags |= I915_ENGINE_FIRST_RENDER_COMPUTE; +- +- /* features common between engines sharing EUs */ +- if (engine->class == RENDER_CLASS || engine->class == COMPUTE_CLASS) { +- engine->flags |= I915_ENGINE_HAS_RCS_REG_STATE; +- engine->flags |= I915_ENGINE_HAS_EU_PRIORITY; +- } ++ /* Cap properties according to any system limits */ ++#define CLAMP_PROP(field) \ ++ do { \ ++ u64 clamp = intel_clamp_##field(engine, engine->props.field); \ ++ if (clamp != engine->props.field) { \ ++ drm_notice(&engine->i915->drm, \ ++ "Warning, clamping %s to %lld to prevent overflow\n", \ ++ #field, clamp); \ ++ engine->props.field = clamp; \ ++ } \ ++ } while (0) ++ ++ CLAMP_PROP(heartbeat_interval_ms); ++ CLAMP_PROP(max_busywait_duration_ns); ++ CLAMP_PROP(preempt_timeout_ms); ++ CLAMP_PROP(stop_timeout_ms); ++ CLAMP_PROP(timeslice_duration_ms); ++ ++#undef CLAMP_PROP + + engine->defaults = engine->props; /* never to change again */ + +@@ -534,6 +554,55 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id, + return 0; + } + ++u64 intel_clamp_heartbeat_interval_ms(struct intel_engine_cs *engine, u64 value) ++{ ++ value = min_t(u64, value, jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT)); ++ ++ return value; ++} ++ ++u64 intel_clamp_max_busywait_duration_ns(struct intel_engine_cs *engine, u64 value) ++{ ++ value = min(value, jiffies_to_nsecs(2)); ++ ++ return value; ++} ++ ++u64 intel_clamp_preempt_timeout_ms(struct intel_engine_cs *engine, u64 value) ++{ ++ /* ++ * NB: The GuC API only supports 32bit values. However, the limit is further ++ * reduced due to internal calculations which would otherwise overflow. ++ */ ++ if (intel_guc_submission_is_wanted(&engine->gt->uc.guc)) ++ value = min_t(u64, value, guc_policy_max_preempt_timeout_ms()); ++ ++ value = min_t(u64, value, jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT)); ++ ++ return value; ++} ++ ++u64 intel_clamp_stop_timeout_ms(struct intel_engine_cs *engine, u64 value) ++{ ++ value = min_t(u64, value, jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT)); ++ ++ return value; ++} ++ ++u64 intel_clamp_timeslice_duration_ms(struct intel_engine_cs *engine, u64 value) ++{ ++ /* ++ * NB: The GuC API only supports 32bit values. However, the limit is further ++ * reduced due to internal calculations which would otherwise overflow. ++ */ ++ if (intel_guc_submission_is_wanted(&engine->gt->uc.guc)) ++ value = min_t(u64, value, guc_policy_max_exec_quantum_ms()); ++ ++ value = min_t(u64, value, jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT)); ++ ++ return value; ++} ++ + static void __setup_engine_capabilities(struct intel_engine_cs *engine) + { + struct drm_i915_private *i915 = engine->i915; +diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c +index 7caa3412a2446..c7db49749a636 100644 +--- a/drivers/gpu/drm/i915/gt/intel_gt.c ++++ b/drivers/gpu/drm/i915/gt/intel_gt.c +@@ -40,8 +40,6 @@ void intel_gt_common_init_early(struct intel_gt *gt) + { + spin_lock_init(gt->irq_lock); + +- INIT_LIST_HEAD(>->lmem_userfault_list); +- mutex_init(>->lmem_userfault_lock); + INIT_LIST_HEAD(>->closed_vma); + spin_lock_init(>->closed_lock); + +@@ -812,7 +810,6 @@ static int intel_gt_tile_setup(struct intel_gt *gt, phys_addr_t phys_addr) + } + + intel_uncore_init_early(gt->uncore, gt); +- intel_wakeref_auto_init(>->userfault_wakeref, gt->uncore->rpm); + + ret = intel_uncore_setup_mmio(gt->uncore, phys_addr); + if (ret) +diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h b/drivers/gpu/drm/i915/gt/intel_gt_types.h +index f19c2de77ff66..184ee9b11a4da 100644 +--- a/drivers/gpu/drm/i915/gt/intel_gt_types.h ++++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h +@@ -141,20 +141,6 @@ struct intel_gt { + struct intel_wakeref wakeref; + atomic_t user_wakeref; + +- /** +- * Protects access to lmem usefault list. +- * It is required, if we are outside of the runtime suspend path, +- * access to @lmem_userfault_list requires always first grabbing the +- * runtime pm, to ensure we can't race against runtime suspend. +- * Once we have that we also need to grab @lmem_userfault_lock, +- * at which point we have exclusive access. +- * The runtime suspend path is special since it doesn't really hold any locks, +- * but instead has exclusive access by virtue of all other accesses requiring +- * holding the runtime pm wakeref. +- */ +- struct mutex lmem_userfault_lock; +- struct list_head lmem_userfault_list; +- + struct list_head closed_vma; + spinlock_t closed_lock; /* guards the list of closed_vma */ + +@@ -170,9 +156,6 @@ struct intel_gt { + */ + intel_wakeref_t awake; + +- /* Manual runtime pm autosuspend delay for user GGTT/lmem mmaps */ +- struct intel_wakeref_auto userfault_wakeref; +- + u32 clock_frequency; + u32 clock_period_ns; + +diff --git a/drivers/gpu/drm/i915/gt/sysfs_engines.c b/drivers/gpu/drm/i915/gt/sysfs_engines.c +index 9670310562029..f2d9858d827c2 100644 +--- a/drivers/gpu/drm/i915/gt/sysfs_engines.c ++++ b/drivers/gpu/drm/i915/gt/sysfs_engines.c +@@ -144,7 +144,7 @@ max_spin_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) + { + struct intel_engine_cs *engine = kobj_to_engine(kobj); +- unsigned long long duration; ++ unsigned long long duration, clamped; + int err; + + /* +@@ -168,7 +168,8 @@ max_spin_store(struct kobject *kobj, struct kobj_attribute *attr, + if (err) + return err; + +- if (duration > jiffies_to_nsecs(2)) ++ clamped = intel_clamp_max_busywait_duration_ns(engine, duration); ++ if (duration != clamped) + return -EINVAL; + + WRITE_ONCE(engine->props.max_busywait_duration_ns, duration); +@@ -203,7 +204,7 @@ timeslice_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) + { + struct intel_engine_cs *engine = kobj_to_engine(kobj); +- unsigned long long duration; ++ unsigned long long duration, clamped; + int err; + + /* +@@ -218,7 +219,8 @@ timeslice_store(struct kobject *kobj, struct kobj_attribute *attr, + if (err) + return err; + +- if (duration > jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT)) ++ clamped = intel_clamp_timeslice_duration_ms(engine, duration); ++ if (duration != clamped) + return -EINVAL; + + WRITE_ONCE(engine->props.timeslice_duration_ms, duration); +@@ -256,7 +258,7 @@ stop_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) + { + struct intel_engine_cs *engine = kobj_to_engine(kobj); +- unsigned long long duration; ++ unsigned long long duration, clamped; + int err; + + /* +@@ -272,7 +274,8 @@ stop_store(struct kobject *kobj, struct kobj_attribute *attr, + if (err) + return err; + +- if (duration > jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT)) ++ clamped = intel_clamp_stop_timeout_ms(engine, duration); ++ if (duration != clamped) + return -EINVAL; + + WRITE_ONCE(engine->props.stop_timeout_ms, duration); +@@ -306,7 +309,7 @@ preempt_timeout_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) + { + struct intel_engine_cs *engine = kobj_to_engine(kobj); +- unsigned long long timeout; ++ unsigned long long timeout, clamped; + int err; + + /* +@@ -322,7 +325,8 @@ preempt_timeout_store(struct kobject *kobj, struct kobj_attribute *attr, + if (err) + return err; + +- if (timeout > jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT)) ++ clamped = intel_clamp_preempt_timeout_ms(engine, timeout); ++ if (timeout != clamped) + return -EINVAL; + + WRITE_ONCE(engine->props.preempt_timeout_ms, timeout); +@@ -362,7 +366,7 @@ heartbeat_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) + { + struct intel_engine_cs *engine = kobj_to_engine(kobj); +- unsigned long long delay; ++ unsigned long long delay, clamped; + int err; + + /* +@@ -379,7 +383,8 @@ heartbeat_store(struct kobject *kobj, struct kobj_attribute *attr, + if (err) + return err; + +- if (delay >= jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT)) ++ clamped = intel_clamp_heartbeat_interval_ms(engine, delay); ++ if (delay != clamped) + return -EINVAL; + + err = intel_engine_set_heartbeat(engine, delay); +diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +index 8f11651460131..685ddccc0f26a 100644 +--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c ++++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +@@ -165,7 +165,7 @@ static const struct __guc_mmio_reg_descr empty_regs_list[] = { + } + + /* List of lists */ +-static struct __guc_mmio_reg_descr_group default_lists[] = { ++static const struct __guc_mmio_reg_descr_group default_lists[] = { + MAKE_REGLIST(default_global_regs, PF, GLOBAL, 0), + MAKE_REGLIST(default_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), + MAKE_REGLIST(xe_lpd_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS), +@@ -419,6 +419,44 @@ guc_capture_get_device_reglist(struct intel_guc *guc) + return default_lists; + } + ++static const char * ++__stringify_type(u32 type) ++{ ++ switch (type) { ++ case GUC_CAPTURE_LIST_TYPE_GLOBAL: ++ return "Global"; ++ case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS: ++ return "Class"; ++ case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE: ++ return "Instance"; ++ default: ++ break; ++ } ++ ++ return "unknown"; ++} ++ ++static const char * ++__stringify_engclass(u32 class) ++{ ++ switch (class) { ++ case GUC_RENDER_CLASS: ++ return "Render"; ++ case GUC_VIDEO_CLASS: ++ return "Video"; ++ case GUC_VIDEOENHANCE_CLASS: ++ return "VideoEnhance"; ++ case GUC_BLITTER_CLASS: ++ return "Blitter"; ++ case GUC_COMPUTE_CLASS: ++ return "Compute"; ++ default: ++ break; ++ } ++ ++ return "unknown"; ++} ++ + static int + guc_capture_list_init(struct intel_guc *guc, u32 owner, u32 type, u32 classid, + struct guc_mmio_reg *ptr, u16 num_entries) +@@ -482,32 +520,55 @@ guc_cap_list_num_regs(struct intel_guc_state_capture *gc, u32 owner, u32 type, u + return num_regs; + } + +-int +-intel_guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid, +- size_t *size) ++static int ++guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid, ++ size_t *size, bool is_purpose_est) + { + struct intel_guc_state_capture *gc = guc->capture; ++ struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + struct __guc_capture_ads_cache *cache = &gc->ads_cache[owner][type][classid]; + int num_regs; + +- if (!gc->reglists) ++ if (!gc->reglists) { ++ drm_warn(&i915->drm, "GuC-capture: No reglist on this device\n"); + return -ENODEV; ++ } + + if (cache->is_valid) { + *size = cache->size; + return cache->status; + } + ++ if (!is_purpose_est && owner == GUC_CAPTURE_LIST_INDEX_PF && ++ !guc_capture_get_one_list(gc->reglists, owner, type, classid)) { ++ if (type == GUC_CAPTURE_LIST_TYPE_GLOBAL) ++ drm_warn(&i915->drm, "Missing GuC-Err-Cap reglist Global!\n"); ++ else ++ drm_warn(&i915->drm, "Missing GuC-Err-Cap reglist %s(%u):%s(%u)!\n", ++ __stringify_type(type), type, ++ __stringify_engclass(classid), classid); ++ return -ENODATA; ++ } ++ + num_regs = guc_cap_list_num_regs(gc, owner, type, classid); ++ /* intentional empty lists can exist depending on hw config */ + if (!num_regs) + return -ENODATA; + +- *size = PAGE_ALIGN((sizeof(struct guc_debug_capture_list)) + +- (num_regs * sizeof(struct guc_mmio_reg))); ++ if (size) ++ *size = PAGE_ALIGN((sizeof(struct guc_debug_capture_list)) + ++ (num_regs * sizeof(struct guc_mmio_reg))); + + return 0; + } + ++int ++intel_guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid, ++ size_t *size) ++{ ++ return guc_capture_getlistsize(guc, owner, type, classid, size, false); ++} ++ + static void guc_capture_create_prealloc_nodes(struct intel_guc *guc); + + int +@@ -606,7 +667,7 @@ guc_capture_output_min_size_est(struct intel_guc *guc) + struct intel_gt *gt = guc_to_gt(guc); + struct intel_engine_cs *engine; + enum intel_engine_id id; +- int worst_min_size = 0, num_regs = 0; ++ int worst_min_size = 0; + size_t tmp = 0; + + if (!guc->capture) +@@ -627,21 +688,19 @@ guc_capture_output_min_size_est(struct intel_guc *guc) + worst_min_size += sizeof(struct guc_state_capture_group_header_t) + + (3 * sizeof(struct guc_state_capture_header_t)); + +- if (!intel_guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, &tmp)) +- num_regs += tmp; ++ if (!guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, &tmp, true)) ++ worst_min_size += tmp; + +- if (!intel_guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, +- engine->class, &tmp)) { +- num_regs += tmp; ++ if (!guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, ++ engine->class, &tmp, true)) { ++ worst_min_size += tmp; + } +- if (!intel_guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE, +- engine->class, &tmp)) { +- num_regs += tmp; ++ if (!guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE, ++ engine->class, &tmp, true)) { ++ worst_min_size += tmp; + } + } + +- worst_min_size += (num_regs * sizeof(struct guc_mmio_reg)); +- + return worst_min_size; + } + +@@ -658,15 +717,23 @@ static void check_guc_capture_size(struct intel_guc *guc) + int spare_size = min_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER; + u32 buffer_size = intel_guc_log_section_size_capture(&guc->log); + ++ /* ++ * NOTE: min_size is much smaller than the capture region allocation (DG2: <80K vs 1MB) ++ * Additionally, its based on space needed to fit all engines getting reset at once ++ * within the same G2H handler task slot. This is very unlikely. However, if GuC really ++ * does run out of space for whatever reason, we will see an separate warning message ++ * when processing the G2H event capture-notification, search for: ++ * INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_NOSPACE. ++ */ + if (min_size < 0) + drm_warn(&i915->drm, "Failed to calculate GuC error state capture buffer minimum size: %d!\n", + min_size); + else if (min_size > buffer_size) +- drm_warn(&i915->drm, "GuC error state capture buffer is too small: %d < %d\n", ++ drm_warn(&i915->drm, "GuC error state capture buffer maybe small: %d < %d\n", + buffer_size, min_size); + else if (spare_size > buffer_size) +- drm_notice(&i915->drm, "GuC error state capture buffer maybe too small: %d < %d (min = %d)\n", +- buffer_size, spare_size, min_size); ++ drm_dbg(&i915->drm, "GuC error state capture buffer lacks spare size: %d < %d (min = %d)\n", ++ buffer_size, spare_size, min_size); + } + + /* +diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +index 323b055e5db97..502e7cb5a3025 100644 +--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h ++++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +@@ -305,6 +305,27 @@ struct guc_update_context_policy { + + #define GLOBAL_POLICY_DEFAULT_DPC_PROMOTE_TIME_US 500000 + ++/* ++ * GuC converts the timeout to clock ticks internally. Different platforms have ++ * different GuC clocks. Thus, the maximum value before overflow is platform ++ * dependent. Current worst case scenario is about 110s. So, the spec says to ++ * limit to 100s to be safe. ++ */ ++#define GUC_POLICY_MAX_EXEC_QUANTUM_US (100 * 1000 * 1000UL) ++#define GUC_POLICY_MAX_PREEMPT_TIMEOUT_US (100 * 1000 * 1000UL) ++ ++static inline u32 guc_policy_max_exec_quantum_ms(void) ++{ ++ BUILD_BUG_ON(GUC_POLICY_MAX_EXEC_QUANTUM_US >= UINT_MAX); ++ return GUC_POLICY_MAX_EXEC_QUANTUM_US / 1000; ++} ++ ++static inline u32 guc_policy_max_preempt_timeout_ms(void) ++{ ++ BUILD_BUG_ON(GUC_POLICY_MAX_PREEMPT_TIMEOUT_US >= UINT_MAX); ++ return GUC_POLICY_MAX_PREEMPT_TIMEOUT_US / 1000; ++} ++ + struct guc_policies { + u32 submission_queue_depth[GUC_MAX_ENGINE_CLASSES]; + /* In micro seconds. How much time to allow before DPC processing is +diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +index 55d3ef93e86f8..68331c538b0a7 100644 +--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c ++++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +@@ -16,15 +16,15 @@ + #if defined(CONFIG_DRM_I915_DEBUG_GUC) + #define GUC_LOG_DEFAULT_CRASH_BUFFER_SIZE SZ_2M + #define GUC_LOG_DEFAULT_DEBUG_BUFFER_SIZE SZ_16M +-#define GUC_LOG_DEFAULT_CAPTURE_BUFFER_SIZE SZ_4M ++#define GUC_LOG_DEFAULT_CAPTURE_BUFFER_SIZE SZ_1M + #elif defined(CONFIG_DRM_I915_DEBUG_GEM) + #define GUC_LOG_DEFAULT_CRASH_BUFFER_SIZE SZ_1M + #define GUC_LOG_DEFAULT_DEBUG_BUFFER_SIZE SZ_2M +-#define GUC_LOG_DEFAULT_CAPTURE_BUFFER_SIZE SZ_4M ++#define GUC_LOG_DEFAULT_CAPTURE_BUFFER_SIZE SZ_1M + #else + #define GUC_LOG_DEFAULT_CRASH_BUFFER_SIZE SZ_8K + #define GUC_LOG_DEFAULT_DEBUG_BUFFER_SIZE SZ_64K +-#define GUC_LOG_DEFAULT_CAPTURE_BUFFER_SIZE SZ_2M ++#define GUC_LOG_DEFAULT_CAPTURE_BUFFER_SIZE SZ_1M + #endif + + static void guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log); +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 1db59eeb34db9..1a23e901cc663 100644 +--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c ++++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +@@ -2429,6 +2429,10 @@ static int guc_context_policy_init_v70(struct intel_context *ce, bool loop) + int ret; + + /* NB: For both of these, zero means disabled. */ ++ GEM_BUG_ON(overflows_type(engine->props.timeslice_duration_ms * 1000, ++ execution_quantum)); ++ GEM_BUG_ON(overflows_type(engine->props.preempt_timeout_ms * 1000, ++ preemption_timeout)); + execution_quantum = engine->props.timeslice_duration_ms * 1000; + preemption_timeout = engine->props.preempt_timeout_ms * 1000; + +@@ -2462,6 +2466,10 @@ static void guc_context_policy_init_v69(struct intel_engine_cs *engine, + desc->policy_flags |= CONTEXT_POLICY_FLAG_PREEMPT_TO_IDLE_V69; + + /* NB: For both of these, zero means disabled. */ ++ GEM_BUG_ON(overflows_type(engine->props.timeslice_duration_ms * 1000, ++ desc->execution_quantum)); ++ GEM_BUG_ON(overflows_type(engine->props.preempt_timeout_ms * 1000, ++ desc->preemption_timeout)); + desc->execution_quantum = engine->props.timeslice_duration_ms * 1000; + desc->preemption_timeout = engine->props.preempt_timeout_ms * 1000; + } +diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c +index f2a15d8155f4a..2ce30cff461a0 100644 +--- a/drivers/gpu/drm/i915/i915_driver.c ++++ b/drivers/gpu/drm/i915/i915_driver.c +@@ -1662,7 +1662,8 @@ static int intel_runtime_suspend(struct device *kdev) + + intel_runtime_pm_enable_interrupts(dev_priv); + +- intel_gt_runtime_resume(to_gt(dev_priv)); ++ for_each_gt(gt, dev_priv, i) ++ intel_gt_runtime_resume(gt); + + enable_rpm_wakeref_asserts(rpm); + +diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c +index 2bdddb61ebd7a..38c26668b9602 100644 +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -843,7 +843,7 @@ void i915_gem_runtime_suspend(struct drm_i915_private *i915) + __i915_gem_object_release_mmap_gtt(obj); + + list_for_each_entry_safe(obj, on, +- &to_gt(i915)->lmem_userfault_list, userfault_link) ++ &i915->runtime_pm.lmem_userfault_list, userfault_link) + i915_gem_object_runtime_pm_release_mmap_offset(obj); + + /* +@@ -1128,6 +1128,8 @@ void i915_gem_drain_workqueue(struct drm_i915_private *i915) + + int i915_gem_init(struct drm_i915_private *dev_priv) + { ++ struct intel_gt *gt; ++ unsigned int i; + int ret; + + /* We need to fallback to 4K pages if host doesn't support huge gtt. */ +@@ -1158,9 +1160,11 @@ int i915_gem_init(struct drm_i915_private *dev_priv) + */ + intel_init_clock_gating(dev_priv); + +- ret = intel_gt_init(to_gt(dev_priv)); +- if (ret) +- goto err_unlock; ++ for_each_gt(gt, dev_priv, i) { ++ ret = intel_gt_init(gt); ++ if (ret) ++ goto err_unlock; ++ } + + return 0; + +@@ -1173,8 +1177,13 @@ int i915_gem_init(struct drm_i915_private *dev_priv) + err_unlock: + i915_gem_drain_workqueue(dev_priv); + +- if (ret != -EIO) +- intel_uc_cleanup_firmwares(&to_gt(dev_priv)->uc); ++ if (ret != -EIO) { ++ for_each_gt(gt, dev_priv, i) { ++ intel_gt_driver_remove(gt); ++ intel_gt_driver_release(gt); ++ intel_uc_cleanup_firmwares(>->uc); ++ } ++ } + + if (ret == -EIO) { + /* +@@ -1182,10 +1191,12 @@ err_unlock: + * as wedged. But we only want to do this when the GPU is angry, + * for all other failure, such as an allocation failure, bail. + */ +- if (!intel_gt_is_wedged(to_gt(dev_priv))) { +- i915_probe_error(dev_priv, +- "Failed to initialize GPU, declaring it wedged!\n"); +- intel_gt_set_wedged(to_gt(dev_priv)); ++ for_each_gt(gt, dev_priv, i) { ++ if (!intel_gt_is_wedged(gt)) { ++ i915_probe_error(dev_priv, ++ "Failed to initialize GPU, declaring it wedged!\n"); ++ intel_gt_set_wedged(gt); ++ } + } + + /* Minimal basic recovery for KMS */ +@@ -1213,10 +1224,12 @@ void i915_gem_driver_unregister(struct drm_i915_private *i915) + + void i915_gem_driver_remove(struct drm_i915_private *dev_priv) + { +- intel_wakeref_auto_fini(&to_gt(dev_priv)->userfault_wakeref); ++ struct intel_gt *gt; ++ unsigned int i; + + i915_gem_suspend_late(dev_priv); +- intel_gt_driver_remove(to_gt(dev_priv)); ++ for_each_gt(gt, dev_priv, i) ++ intel_gt_driver_remove(gt); + dev_priv->uabi_engines = RB_ROOT; + + /* Flush any outstanding unpin_work. */ +@@ -1227,9 +1240,13 @@ void i915_gem_driver_remove(struct drm_i915_private *dev_priv) + + void i915_gem_driver_release(struct drm_i915_private *dev_priv) + { +- intel_gt_driver_release(to_gt(dev_priv)); ++ struct intel_gt *gt; ++ unsigned int i; + +- intel_uc_cleanup_firmwares(&to_gt(dev_priv)->uc); ++ for_each_gt(gt, dev_priv, i) { ++ intel_gt_driver_release(gt); ++ intel_uc_cleanup_firmwares(>->uc); ++ } + + /* Flush any outstanding work, including i915_gem_context.release_work. */ + i915_gem_drain_workqueue(dev_priv); +diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c +index 744cca507946b..129746713d072 100644 +--- a/drivers/gpu/drm/i915/intel_runtime_pm.c ++++ b/drivers/gpu/drm/i915/intel_runtime_pm.c +@@ -633,6 +633,8 @@ void intel_runtime_pm_driver_release(struct intel_runtime_pm *rpm) + runtime_pm); + int count = atomic_read(&rpm->wakeref_count); + ++ intel_wakeref_auto_fini(&rpm->userfault_wakeref); ++ + drm_WARN(&i915->drm, count, + "i915 raw-wakerefs=%d wakelocks=%d on cleanup\n", + intel_rpm_raw_wakeref_count(count), +@@ -652,4 +654,7 @@ void intel_runtime_pm_init_early(struct intel_runtime_pm *rpm) + rpm->available = HAS_RUNTIME_PM(i915); + + init_intel_runtime_pm_wakeref(rpm); ++ INIT_LIST_HEAD(&rpm->lmem_userfault_list); ++ spin_lock_init(&rpm->lmem_userfault_lock); ++ intel_wakeref_auto_init(&rpm->userfault_wakeref, rpm); + } +diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.h b/drivers/gpu/drm/i915/intel_runtime_pm.h +index d9160e3ff4afc..98b8b28baaa15 100644 +--- a/drivers/gpu/drm/i915/intel_runtime_pm.h ++++ b/drivers/gpu/drm/i915/intel_runtime_pm.h +@@ -53,6 +53,28 @@ struct intel_runtime_pm { + bool irqs_enabled; + bool no_wakeref_tracking; + ++ /* ++ * Protects access to lmem usefault list. ++ * It is required, if we are outside of the runtime suspend path, ++ * access to @lmem_userfault_list requires always first grabbing the ++ * runtime pm, to ensure we can't race against runtime suspend. ++ * Once we have that we also need to grab @lmem_userfault_lock, ++ * at which point we have exclusive access. ++ * The runtime suspend path is special since it doesn't really hold any locks, ++ * but instead has exclusive access by virtue of all other accesses requiring ++ * holding the runtime pm wakeref. ++ */ ++ spinlock_t lmem_userfault_lock; ++ ++ /* ++ * Keep list of userfaulted gem obj, which require to release their ++ * mmap mappings at runtime suspend path. ++ */ ++ struct list_head lmem_userfault_list; ++ ++ /* Manual runtime pm autosuspend delay for user GGTT/lmem mmaps */ ++ struct intel_wakeref_auto userfault_wakeref; ++ + #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) + /* + * To aide detection of wakeref leaks and general misuse, we +diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c +index 508a6d994e831..1f5d39a4077cd 100644 +--- a/drivers/gpu/drm/mediatek/mtk_dpi.c ++++ b/drivers/gpu/drm/mediatek/mtk_dpi.c +@@ -461,9 +461,6 @@ static void mtk_dpi_power_off(struct mtk_dpi *dpi) + if (--dpi->refcount != 0) + return; + +- if (dpi->pinctrl && dpi->pins_gpio) +- pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio); +- + mtk_dpi_disable(dpi); + clk_disable_unprepare(dpi->pixel_clk); + clk_disable_unprepare(dpi->engine_clk); +@@ -488,9 +485,6 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi) + goto err_pixel; + } + +- if (dpi->pinctrl && dpi->pins_dpi) +- pinctrl_select_state(dpi->pinctrl, dpi->pins_dpi); +- + return 0; + + err_pixel: +@@ -721,12 +715,18 @@ static void mtk_dpi_bridge_disable(struct drm_bridge *bridge) + struct mtk_dpi *dpi = bridge_to_dpi(bridge); + + mtk_dpi_power_off(dpi); ++ ++ if (dpi->pinctrl && dpi->pins_gpio) ++ pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio); + } + + static void mtk_dpi_bridge_enable(struct drm_bridge *bridge) + { + struct mtk_dpi *dpi = bridge_to_dpi(bridge); + ++ if (dpi->pinctrl && dpi->pins_dpi) ++ pinctrl_select_state(dpi->pinctrl, dpi->pins_dpi); ++ + mtk_dpi_power_on(dpi); + mtk_dpi_set_display_mode(dpi, &dpi->mode); + mtk_dpi_enable(dpi); +diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c +index 4c80b6896dc3d..6e8f99554f548 100644 +--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c ++++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c +@@ -1202,9 +1202,10 @@ static enum drm_connector_status mtk_hdmi_detect(struct mtk_hdmi *hdmi) + return mtk_hdmi_update_plugged_status(hdmi); + } + +-static int mtk_hdmi_bridge_mode_valid(struct drm_bridge *bridge, +- const struct drm_display_info *info, +- const struct drm_display_mode *mode) ++static enum drm_mode_status ++mtk_hdmi_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, ++ const struct drm_display_mode *mode) + { + struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); + struct drm_bridge *next_bridge; +diff --git a/drivers/gpu/drm/meson/meson_encoder_cvbs.c b/drivers/gpu/drm/meson/meson_encoder_cvbs.c +index 5675bc2a92cf8..3f73b211fa8e3 100644 +--- a/drivers/gpu/drm/meson/meson_encoder_cvbs.c ++++ b/drivers/gpu/drm/meson/meson_encoder_cvbs.c +@@ -116,9 +116,10 @@ static int meson_encoder_cvbs_get_modes(struct drm_bridge *bridge, + return i; + } + +-static int meson_encoder_cvbs_mode_valid(struct drm_bridge *bridge, +- const struct drm_display_info *display_info, +- const struct drm_display_mode *mode) ++static enum drm_mode_status ++meson_encoder_cvbs_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *display_info, ++ const struct drm_display_mode *mode) + { + if (meson_cvbs_get_mode(mode)) + return MODE_OK; +diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +index fdc578016e0bf..e846e629c00d8 100644 +--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c ++++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +@@ -1906,7 +1906,7 @@ static u32 fuse_to_supp_hw(struct device *dev, struct adreno_rev rev, u32 fuse) + + if (val == UINT_MAX) { + DRM_DEV_ERROR(dev, +- "missing support for speed-bin: %u. Some OPPs may not be supported by hardware", ++ "missing support for speed-bin: %u. Some OPPs may not be supported by hardware\n", + fuse); + return UINT_MAX; + } +@@ -1916,7 +1916,7 @@ static u32 fuse_to_supp_hw(struct device *dev, struct adreno_rev rev, u32 fuse) + + static int a6xx_set_supported_hw(struct device *dev, struct adreno_rev rev) + { +- u32 supp_hw = UINT_MAX; ++ u32 supp_hw; + u32 speedbin; + int ret; + +@@ -1928,15 +1928,13 @@ static int a6xx_set_supported_hw(struct device *dev, struct adreno_rev rev) + if (ret == -ENOENT) { + return 0; + } else if (ret) { +- DRM_DEV_ERROR(dev, +- "failed to read speed-bin (%d). Some OPPs may not be supported by hardware", +- ret); +- goto done; ++ dev_err_probe(dev, ret, ++ "failed to read speed-bin. Some OPPs may not be supported by hardware\n"); ++ return ret; + } + + supp_hw = fuse_to_supp_hw(dev, rev, speedbin); + +-done: + ret = devm_pm_opp_set_supported_hw(dev, &supp_hw, 1); + if (ret) + return ret; +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c +index f2ddcfb6f7ee6..3662df698dae5 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c +@@ -42,7 +42,7 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc, + u32 initial_lines) + { + struct dpu_hw_blk_reg_map *c = &hw_dsc->hw; +- u32 data, lsb, bpp; ++ u32 data; + u32 slice_last_group_size; + u32 det_thresh_flatness; + bool is_cmd_mode = !(mode & DSC_MODE_VIDEO); +@@ -56,14 +56,7 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc, + data = (initial_lines << 20); + data |= ((slice_last_group_size - 1) << 18); + /* bpp is 6.4 format, 4 LSBs bits are for fractional part */ +- data |= dsc->bits_per_pixel << 12; +- lsb = dsc->bits_per_pixel % 4; +- bpp = dsc->bits_per_pixel / 4; +- bpp *= 4; +- bpp <<= 4; +- bpp |= lsb; +- +- data |= bpp << 8; ++ data |= (dsc->bits_per_pixel << 8); + data |= (dsc->block_pred_enable << 7); + data |= (dsc->line_buf_depth << 3); + data |= (dsc->simple_422 << 2); +diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +index b0d21838a1343..29ae5c9613f36 100644 +--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c ++++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +@@ -203,7 +203,7 @@ static int mdp5_set_split_display(struct msm_kms *kms, + slave_encoder); + } + +-static void mdp5_destroy(struct platform_device *pdev); ++static void mdp5_destroy(struct mdp5_kms *mdp5_kms); + + static void mdp5_kms_destroy(struct msm_kms *kms) + { +@@ -223,7 +223,7 @@ static void mdp5_kms_destroy(struct msm_kms *kms) + } + + mdp_kms_destroy(&mdp5_kms->base); +- mdp5_destroy(mdp5_kms->pdev); ++ mdp5_destroy(mdp5_kms); + } + + #ifdef CONFIG_DEBUG_FS +@@ -559,6 +559,8 @@ static int mdp5_kms_init(struct drm_device *dev) + int irq, i, ret; + + ret = mdp5_init(to_platform_device(dev->dev), dev); ++ if (ret) ++ return ret; + + /* priv->kms would have been populated by the MDP5 driver */ + kms = priv->kms; +@@ -632,9 +634,8 @@ fail: + return ret; + } + +-static void mdp5_destroy(struct platform_device *pdev) ++static void mdp5_destroy(struct mdp5_kms *mdp5_kms) + { +- struct mdp5_kms *mdp5_kms = platform_get_drvdata(pdev); + int i; + + if (mdp5_kms->ctlm) +@@ -648,7 +649,7 @@ static void mdp5_destroy(struct platform_device *pdev) + kfree(mdp5_kms->intfs[i]); + + if (mdp5_kms->rpm_enabled) +- pm_runtime_disable(&pdev->dev); ++ pm_runtime_disable(&mdp5_kms->pdev->dev); + + drm_atomic_private_obj_fini(&mdp5_kms->glob_state); + drm_modeset_lock_fini(&mdp5_kms->glob_state_lock); +@@ -797,8 +798,6 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev) + goto fail; + } + +- platform_set_drvdata(pdev, mdp5_kms); +- + spin_lock_init(&mdp5_kms->resource_lock); + + mdp5_kms->dev = dev; +@@ -839,6 +838,9 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev) + */ + clk_set_rate(mdp5_kms->core_clk, 200000000); + ++ /* set uninit-ed kms */ ++ priv->kms = &mdp5_kms->base.base; ++ + pm_runtime_enable(&pdev->dev); + mdp5_kms->rpm_enabled = true; + +@@ -890,13 +892,10 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev) + if (ret) + goto fail; + +- /* set uninit-ed kms */ +- priv->kms = &mdp5_kms->base.base; +- + return 0; + fail: + if (mdp5_kms) +- mdp5_destroy(pdev); ++ mdp5_destroy(mdp5_kms); + return ret; + } + +@@ -953,7 +952,8 @@ static int mdp5_dev_remove(struct platform_device *pdev) + static __maybe_unused int mdp5_runtime_suspend(struct device *dev) + { + struct platform_device *pdev = to_platform_device(dev); +- struct mdp5_kms *mdp5_kms = platform_get_drvdata(pdev); ++ struct msm_drm_private *priv = platform_get_drvdata(pdev); ++ struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms)); + + DBG(""); + +@@ -963,7 +963,8 @@ static __maybe_unused int mdp5_runtime_suspend(struct device *dev) + static __maybe_unused int mdp5_runtime_resume(struct device *dev) + { + struct platform_device *pdev = to_platform_device(dev); +- struct mdp5_kms *mdp5_kms = platform_get_drvdata(pdev); ++ struct msm_drm_private *priv = platform_get_drvdata(pdev); ++ struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms)); + + DBG(""); + +diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c +index a49f6dbbe8883..c9d9b384ddd03 100644 +--- a/drivers/gpu/drm/msm/dp/dp_display.c ++++ b/drivers/gpu/drm/msm/dp/dp_display.c +@@ -857,7 +857,7 @@ static int dp_display_set_mode(struct msm_dp *dp_display, + + dp = container_of(dp_display, struct dp_display_private, dp_display); + +- dp->panel->dp_mode.drm_mode = mode->drm_mode; ++ drm_mode_copy(&dp->panel->dp_mode.drm_mode, &mode->drm_mode); + dp->panel->dp_mode.bpp = mode->bpp; + dp->panel->dp_mode.capabilities = mode->capabilities; + dp_panel_init_panel_info(dp->panel); +diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c +index 7fbf391c024f8..89aadd3b3202b 100644 +--- a/drivers/gpu/drm/msm/dsi/dsi_host.c ++++ b/drivers/gpu/drm/msm/dsi/dsi_host.c +@@ -21,6 +21,7 @@ + + #include <video/mipi_display.h> + ++#include <drm/display/drm_dsc_helper.h> + #include <drm/drm_of.h> + + #include "dsi.h" +@@ -33,7 +34,7 @@ + + #define DSI_RESET_TOGGLE_DELAY_MS 20 + +-static int dsi_populate_dsc_params(struct drm_dsc_config *dsc); ++static int dsi_populate_dsc_params(struct msm_dsi_host *msm_host, struct drm_dsc_config *dsc); + + static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor) + { +@@ -842,17 +843,15 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable, + static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mode, u32 hdisplay) + { + struct drm_dsc_config *dsc = msm_host->dsc; +- u32 reg, intf_width, reg_ctrl, reg_ctrl2; ++ u32 reg, reg_ctrl, reg_ctrl2; + u32 slice_per_intf, total_bytes_per_intf; + u32 pkt_per_line; +- u32 bytes_in_slice; + u32 eol_byte_num; + + /* first calculate dsc parameters and then program + * compress mode registers + */ +- intf_width = hdisplay; +- slice_per_intf = DIV_ROUND_UP(intf_width, dsc->slice_width); ++ slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->slice_width); + + /* If slice_per_pkt is greater than slice_per_intf + * then default to 1. This can happen during partial +@@ -861,12 +860,7 @@ static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mod + if (slice_per_intf > dsc->slice_count) + dsc->slice_count = 1; + +- slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->slice_width); +- bytes_in_slice = DIV_ROUND_UP(dsc->slice_width * dsc->bits_per_pixel, 8); +- +- dsc->slice_chunk_size = bytes_in_slice; +- +- total_bytes_per_intf = bytes_in_slice * slice_per_intf; ++ total_bytes_per_intf = dsc->slice_chunk_size * slice_per_intf; + + eol_byte_num = total_bytes_per_intf % 3; + pkt_per_line = slice_per_intf / dsc->slice_count; +@@ -892,7 +886,7 @@ static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mod + reg_ctrl |= reg; + + reg_ctrl2 &= ~DSI_COMMAND_COMPRESSION_MODE_CTRL2_STREAM0_SLICE_WIDTH__MASK; +- reg_ctrl2 |= DSI_COMMAND_COMPRESSION_MODE_CTRL2_STREAM0_SLICE_WIDTH(bytes_in_slice); ++ reg_ctrl2 |= DSI_COMMAND_COMPRESSION_MODE_CTRL2_STREAM0_SLICE_WIDTH(dsc->slice_chunk_size); + + dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL, reg_ctrl); + dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2, reg_ctrl2); +@@ -915,6 +909,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) + u32 va_end = va_start + mode->vdisplay; + u32 hdisplay = mode->hdisplay; + u32 wc; ++ int ret; + + DBG(""); + +@@ -950,7 +945,9 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) + /* we do the calculations for dsc parameters here so that + * panel can use these parameters + */ +- dsi_populate_dsc_params(dsc); ++ ret = dsi_populate_dsc_params(msm_host, dsc); ++ if (ret) ++ return; + + /* Divide the display by 3 but keep back/font porch and + * pulse width same +@@ -1754,18 +1751,20 @@ static char bpg_offset[DSC_NUM_BUF_RANGES] = { + 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 + }; + +-static int dsi_populate_dsc_params(struct drm_dsc_config *dsc) +-{ +- int mux_words_size; +- int groups_per_line, groups_total; +- int min_rate_buffer_size; +- int hrd_delay; +- int pre_num_extra_mux_bits, num_extra_mux_bits; +- int slice_bits; +- int target_bpp_x16; +- int data; +- int final_value, final_scale; ++static int dsi_populate_dsc_params(struct msm_dsi_host *msm_host, struct drm_dsc_config *dsc) ++{ + int i; ++ u16 bpp = dsc->bits_per_pixel >> 4; ++ ++ if (dsc->bits_per_pixel & 0xf) { ++ DRM_DEV_ERROR(&msm_host->pdev->dev, "DSI does not support fractional bits_per_pixel\n"); ++ return -EINVAL; ++ } ++ ++ if (dsc->bits_per_component != 8) { ++ DRM_DEV_ERROR(&msm_host->pdev->dev, "DSI does not support bits_per_component != 8 yet\n"); ++ return -EOPNOTSUPP; ++ } + + dsc->rc_model_size = 8192; + dsc->first_line_bpg_offset = 12; +@@ -1783,16 +1782,21 @@ static int dsi_populate_dsc_params(struct drm_dsc_config *dsc) + for (i = 0; i < DSC_NUM_BUF_RANGES; i++) { + dsc->rc_range_params[i].range_min_qp = min_qp[i]; + dsc->rc_range_params[i].range_max_qp = max_qp[i]; +- dsc->rc_range_params[i].range_bpg_offset = bpg_offset[i]; ++ /* ++ * Range BPG Offset contains two's-complement signed values that fill ++ * 8 bits, yet the registers and DCS PPS field are only 6 bits wide. ++ */ ++ dsc->rc_range_params[i].range_bpg_offset = bpg_offset[i] & DSC_RANGE_BPG_OFFSET_MASK; + } + +- dsc->initial_offset = 6144; /* Not bpp 12 */ +- if (dsc->bits_per_pixel != 8) ++ dsc->initial_offset = 6144; /* Not bpp 12 */ ++ if (bpp != 8) + dsc->initial_offset = 2048; /* bpp = 12 */ + +- mux_words_size = 48; /* bpc == 8/10 */ +- if (dsc->bits_per_component == 12) +- mux_words_size = 64; ++ if (dsc->bits_per_component <= 10) ++ dsc->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC; ++ else ++ dsc->mux_word_size = DSC_MUX_WORD_SIZE_12_BPC; + + dsc->initial_xmit_delay = 512; + dsc->initial_scale_value = 32; +@@ -1804,63 +1808,8 @@ static int dsi_populate_dsc_params(struct drm_dsc_config *dsc) + dsc->flatness_max_qp = 12; + dsc->rc_quant_incr_limit0 = 11; + dsc->rc_quant_incr_limit1 = 11; +- dsc->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC; +- +- /* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of +- * params are calculated +- */ +- groups_per_line = DIV_ROUND_UP(dsc->slice_width, 3); +- dsc->slice_chunk_size = dsc->slice_width * dsc->bits_per_pixel / 8; +- if ((dsc->slice_width * dsc->bits_per_pixel) % 8) +- dsc->slice_chunk_size++; + +- /* rbs-min */ +- min_rate_buffer_size = dsc->rc_model_size - dsc->initial_offset + +- dsc->initial_xmit_delay * dsc->bits_per_pixel + +- groups_per_line * dsc->first_line_bpg_offset; +- +- hrd_delay = DIV_ROUND_UP(min_rate_buffer_size, dsc->bits_per_pixel); +- +- dsc->initial_dec_delay = hrd_delay - dsc->initial_xmit_delay; +- +- dsc->initial_scale_value = 8 * dsc->rc_model_size / +- (dsc->rc_model_size - dsc->initial_offset); +- +- slice_bits = 8 * dsc->slice_chunk_size * dsc->slice_height; +- +- groups_total = groups_per_line * dsc->slice_height; +- +- data = dsc->first_line_bpg_offset * 2048; +- +- dsc->nfl_bpg_offset = DIV_ROUND_UP(data, (dsc->slice_height - 1)); +- +- pre_num_extra_mux_bits = 3 * (mux_words_size + (4 * dsc->bits_per_component + 4) - 2); +- +- num_extra_mux_bits = pre_num_extra_mux_bits - (mux_words_size - +- ((slice_bits - pre_num_extra_mux_bits) % mux_words_size)); +- +- data = 2048 * (dsc->rc_model_size - dsc->initial_offset + num_extra_mux_bits); +- dsc->slice_bpg_offset = DIV_ROUND_UP(data, groups_total); +- +- /* bpp * 16 + 0.5 */ +- data = dsc->bits_per_pixel * 16; +- data *= 2; +- data++; +- data /= 2; +- target_bpp_x16 = data; +- +- data = (dsc->initial_xmit_delay * target_bpp_x16) / 16; +- final_value = dsc->rc_model_size - data + num_extra_mux_bits; +- dsc->final_offset = final_value; +- +- final_scale = 8 * dsc->rc_model_size / (dsc->rc_model_size - final_value); +- +- data = (final_scale - 9) * (dsc->nfl_bpg_offset + dsc->slice_bpg_offset); +- dsc->scale_increment_interval = (2048 * dsc->final_offset) / data; +- +- dsc->scale_decrement_interval = groups_per_line / (dsc->initial_scale_value - 8); +- +- return 0; ++ return drm_dsc_compute_rc_parameters(dsc); + } + + static int dsi_host_parse_dt(struct msm_dsi_host *msm_host) +diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c +index f28fb21e38911..8cd5d50639a53 100644 +--- a/drivers/gpu/drm/msm/hdmi/hdmi.c ++++ b/drivers/gpu/drm/msm/hdmi/hdmi.c +@@ -252,7 +252,7 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev) + if (hdmi->hpd_gpiod) + gpiod_set_consumer_name(hdmi->hpd_gpiod, "HDMI_HPD"); + +- pm_runtime_enable(&pdev->dev); ++ devm_pm_runtime_enable(&pdev->dev); + + hdmi->workq = alloc_ordered_workqueue("msm_hdmi", 0); + +diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c b/drivers/gpu/drm/mxsfb/lcdif_kms.c +index b1092aab14231..71546a5d0a48c 100644 +--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c ++++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c +@@ -5,6 +5,7 @@ + * This code is based on drivers/gpu/drm/mxsfb/mxsfb* + */ + ++#include <linux/bitfield.h> + #include <linux/clk.h> + #include <linux/io.h> + #include <linux/iopoll.h> +@@ -52,16 +53,22 @@ static void lcdif_set_formats(struct lcdif_drm_private *lcdif, + writel(DISP_PARA_LINE_PATTERN_UYVY_H, + lcdif->base + LCDC_V8_DISP_PARA); + +- /* CSC: BT.601 Full Range RGB to YCbCr coefficients. */ +- writel(CSC0_COEF0_A2(0x096) | CSC0_COEF0_A1(0x04c), ++ /* ++ * CSC: BT.601 Limited Range RGB to YCbCr coefficients. ++ * ++ * |Y | | 0.2568 0.5041 0.0979| |R| |16 | ++ * |Cb| = |-0.1482 -0.2910 0.4392| * |G| + |128| ++ * |Cr| | 0.4392 0.4392 -0.3678| |B| |128| ++ */ ++ writel(CSC0_COEF0_A2(0x081) | CSC0_COEF0_A1(0x041), + lcdif->base + LCDC_V8_CSC0_COEF0); +- writel(CSC0_COEF1_B1(0x7d5) | CSC0_COEF1_A3(0x01d), ++ writel(CSC0_COEF1_B1(0x7db) | CSC0_COEF1_A3(0x019), + lcdif->base + LCDC_V8_CSC0_COEF1); +- writel(CSC0_COEF2_B3(0x080) | CSC0_COEF2_B2(0x7ac), ++ writel(CSC0_COEF2_B3(0x070) | CSC0_COEF2_B2(0x7b6), + lcdif->base + LCDC_V8_CSC0_COEF2); +- writel(CSC0_COEF3_C2(0x795) | CSC0_COEF3_C1(0x080), ++ writel(CSC0_COEF3_C2(0x7a2) | CSC0_COEF3_C1(0x070), + lcdif->base + LCDC_V8_CSC0_COEF3); +- writel(CSC0_COEF4_D1(0x000) | CSC0_COEF4_C3(0x7ec), ++ writel(CSC0_COEF4_D1(0x010) | CSC0_COEF4_C3(0x7ee), + lcdif->base + LCDC_V8_CSC0_COEF4); + writel(CSC0_COEF5_D3(0x080) | CSC0_COEF5_D2(0x080), + lcdif->base + LCDC_V8_CSC0_COEF5); +@@ -142,14 +149,36 @@ static void lcdif_set_mode(struct lcdif_drm_private *lcdif, u32 bus_flags) + CTRLDESCL0_1_WIDTH(m->hdisplay), + lcdif->base + LCDC_V8_CTRLDESCL0_1); + +- writel(CTRLDESCL0_3_PITCH(lcdif->crtc.primary->state->fb->pitches[0]), +- lcdif->base + LCDC_V8_CTRLDESCL0_3); ++ /* ++ * Undocumented P_SIZE and T_SIZE register but those written in the ++ * downstream kernel those registers control the AXI burst size. As of ++ * now there are two known values: ++ * 1 - 128Byte ++ * 2 - 256Byte ++ * Downstream set it to 256B burst size to improve the memory ++ * efficiency so set it here too. ++ */ ++ ctrl = CTRLDESCL0_3_P_SIZE(2) | CTRLDESCL0_3_T_SIZE(2) | ++ CTRLDESCL0_3_PITCH(lcdif->crtc.primary->state->fb->pitches[0]); ++ writel(ctrl, lcdif->base + LCDC_V8_CTRLDESCL0_3); + } + + static void lcdif_enable_controller(struct lcdif_drm_private *lcdif) + { + u32 reg; + ++ /* Set FIFO Panic watermarks, low 1/3, high 2/3 . */ ++ writel(FIELD_PREP(PANIC0_THRES_LOW_MASK, 1 * PANIC0_THRES_MAX / 3) | ++ FIELD_PREP(PANIC0_THRES_HIGH_MASK, 2 * PANIC0_THRES_MAX / 3), ++ lcdif->base + LCDC_V8_PANIC0_THRES); ++ ++ /* ++ * Enable FIFO Panic, this does not generate interrupt, but ++ * boosts NoC priority based on FIFO Panic watermarks. ++ */ ++ writel(INT_ENABLE_D1_PLANE_PANIC_EN, ++ lcdif->base + LCDC_V8_INT_ENABLE_D1); ++ + reg = readl(lcdif->base + LCDC_V8_DISP_PARA); + reg |= DISP_PARA_DISP_ON; + writel(reg, lcdif->base + LCDC_V8_DISP_PARA); +@@ -177,6 +206,9 @@ static void lcdif_disable_controller(struct lcdif_drm_private *lcdif) + reg = readl(lcdif->base + LCDC_V8_DISP_PARA); + reg &= ~DISP_PARA_DISP_ON; + writel(reg, lcdif->base + LCDC_V8_DISP_PARA); ++ ++ /* Disable FIFO Panic NoC priority booster. */ ++ writel(0, lcdif->base + LCDC_V8_INT_ENABLE_D1); + } + + static void lcdif_reset_block(struct lcdif_drm_private *lcdif) +diff --git a/drivers/gpu/drm/mxsfb/lcdif_regs.h b/drivers/gpu/drm/mxsfb/lcdif_regs.h +index c70220651e3a5..37f0d9a06b104 100644 +--- a/drivers/gpu/drm/mxsfb/lcdif_regs.h ++++ b/drivers/gpu/drm/mxsfb/lcdif_regs.h +@@ -190,6 +190,10 @@ + #define CTRLDESCL0_1_WIDTH(n) ((n) & 0xffff) + #define CTRLDESCL0_1_WIDTH_MASK GENMASK(15, 0) + ++#define CTRLDESCL0_3_P_SIZE(n) (((n) << 20) & CTRLDESCL0_3_P_SIZE_MASK) ++#define CTRLDESCL0_3_P_SIZE_MASK GENMASK(22, 20) ++#define CTRLDESCL0_3_T_SIZE(n) (((n) << 16) & CTRLDESCL0_3_T_SIZE_MASK) ++#define CTRLDESCL0_3_T_SIZE_MASK GENMASK(17, 16) + #define CTRLDESCL0_3_PITCH(n) ((n) & 0xffff) + #define CTRLDESCL0_3_PITCH_MASK GENMASK(15, 0) + +@@ -248,6 +252,7 @@ + + #define PANIC0_THRES_LOW_MASK GENMASK(24, 16) + #define PANIC0_THRES_HIGH_MASK GENMASK(8, 0) ++#define PANIC0_THRES_MAX 511 + + #define LCDIF_MIN_XRES 120 + #define LCDIF_MIN_YRES 120 +diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c +index c481daa4bbceb..225b9884f61a9 100644 +--- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c ++++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c +@@ -244,7 +244,7 @@ static void st7701_init_sequence(struct st7701 *st7701) + DSI_CMD2_BK0_INVSEL_ONES_MASK | + FIELD_PREP(DSI_CMD2_BK0_INVSEL_NLINV_MASK, desc->nlinv), + FIELD_PREP(DSI_CMD2_BK0_INVSEL_RTNI_MASK, +- DIV_ROUND_UP(mode->htotal, 16))); ++ (clamp((u32)mode->htotal, 512U, 1008U) - 512) / 16)); + + /* Command2, BK1 */ + ST7701_DSI(st7701, DSI_CMD2BKX_SEL, +@@ -762,7 +762,15 @@ static int st7701_dsi_probe(struct mipi_dsi_device *dsi) + st7701->dsi = dsi; + st7701->desc = desc; + +- return mipi_dsi_attach(dsi); ++ ret = mipi_dsi_attach(dsi); ++ if (ret) ++ goto err_attach; ++ ++ return 0; ++ ++err_attach: ++ drm_panel_remove(&st7701->panel); ++ return ret; + } + + static void st7701_dsi_remove(struct mipi_dsi_device *dsi) +diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c +index 33121655d50bb..63bdc9f6fc243 100644 +--- a/drivers/gpu/drm/radeon/radeon_bios.c ++++ b/drivers/gpu/drm/radeon/radeon_bios.c +@@ -227,6 +227,7 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) + + if (!found) + return false; ++ pci_dev_put(pdev); + + rdev->bios = kmalloc(size, GFP_KERNEL); + if (!rdev->bios) { +@@ -612,13 +613,14 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) + acpi_size tbl_size; + UEFI_ACPI_VFCT *vfct; + unsigned offset; ++ bool r = false; + + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) + return false; + tbl_size = hdr->length; + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); +- return false; ++ goto out; + } + + vfct = (UEFI_ACPI_VFCT *)hdr; +@@ -631,13 +633,13 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) + offset += sizeof(VFCT_IMAGE_HEADER); + if (offset > tbl_size) { + DRM_ERROR("ACPI VFCT image header truncated\n"); +- return false; ++ goto out; + } + + offset += vhdr->ImageLength; + if (offset > tbl_size) { + DRM_ERROR("ACPI VFCT image truncated\n"); +- return false; ++ goto out; + } + + if (vhdr->ImageLength && +@@ -649,15 +651,18 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) + rdev->bios = kmemdup(&vbios->VbiosContent, + vhdr->ImageLength, + GFP_KERNEL); ++ if (rdev->bios) ++ r = true; + +- if (!rdev->bios) +- return false; +- return true; ++ goto out; + } + } + + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); +- return false; ++ ++out: ++ acpi_put_table(hdr); ++ return r; + } + #else + static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig +index fd2c2eaee26ba..a5518e90d6896 100644 +--- a/drivers/gpu/drm/rcar-du/Kconfig ++++ b/drivers/gpu/drm/rcar-du/Kconfig +@@ -41,8 +41,6 @@ config DRM_RCAR_LVDS + depends on DRM_RCAR_USE_LVDS + select DRM_KMS_HELPER + select DRM_PANEL +- select OF_FLATTREE +- select OF_OVERLAY + + config DRM_RCAR_USE_MIPI_DSI + bool "R-Car DU MIPI DSI Encoder Support" +diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c +index 518ee13b1d6f4..8526dda919317 100644 +--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c ++++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c +@@ -571,7 +571,7 @@ static void cdn_dp_encoder_mode_set(struct drm_encoder *encoder, + video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC); + video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC); + +- memcpy(&dp->mode, adjusted, sizeof(*mode)); ++ drm_mode_copy(&dp->mode, adjusted); + } + + static bool cdn_dp_check_link_status(struct cdn_dp_device *dp) +diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +index f4df9820b295d..912eb4e94c595 100644 +--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +@@ -1221,7 +1221,7 @@ static int dw_mipi_dsi_dphy_power_on(struct phy *phy) + return i; + } + +- ret = pm_runtime_get_sync(dsi->dev); ++ ret = pm_runtime_resume_and_get(dsi->dev); + if (ret < 0) { + DRM_DEV_ERROR(dsi->dev, "failed to enable device: %d\n", ret); + return ret; +diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c +index 87b2243ea23e3..f51774866f412 100644 +--- a/drivers/gpu/drm/rockchip/inno_hdmi.c ++++ b/drivers/gpu/drm/rockchip/inno_hdmi.c +@@ -499,7 +499,7 @@ static void inno_hdmi_encoder_mode_set(struct drm_encoder *encoder, + inno_hdmi_setup(hdmi, adj_mode); + + /* Store the display mode for plugin/DPMS poweron events */ +- memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode)); ++ drm_mode_copy(&hdmi->previous_mode, adj_mode); + } + + static void inno_hdmi_encoder_enable(struct drm_encoder *encoder) +diff --git a/drivers/gpu/drm/rockchip/rk3066_hdmi.c b/drivers/gpu/drm/rockchip/rk3066_hdmi.c +index cf2cf51091a3e..90145ad969841 100644 +--- a/drivers/gpu/drm/rockchip/rk3066_hdmi.c ++++ b/drivers/gpu/drm/rockchip/rk3066_hdmi.c +@@ -395,7 +395,7 @@ rk3066_hdmi_encoder_mode_set(struct drm_encoder *encoder, + struct rk3066_hdmi *hdmi = encoder_to_rk3066_hdmi(encoder); + + /* Store the display mode for plugin/DPMS poweron events. */ +- memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode)); ++ drm_mode_copy(&hdmi->previous_mode, adj_mode); + } + + static void rk3066_hdmi_encoder_enable(struct drm_encoder *encoder) +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index c356de5dd2206..fa1f4ee6d1950 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -602,7 +602,7 @@ static int vop_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) + struct vop *vop = to_vop(crtc); + int ret, i; + +- ret = pm_runtime_get_sync(vop->dev); ++ ret = pm_runtime_resume_and_get(vop->dev); + if (ret < 0) { + DRM_DEV_ERROR(vop->dev, "failed to get pm runtime: %d\n", ret); + return ret; +@@ -1983,7 +1983,7 @@ static int vop_initial(struct vop *vop) + return PTR_ERR(vop->dclk); + } + +- ret = pm_runtime_get_sync(vop->dev); ++ ret = pm_runtime_resume_and_get(vop->dev); + if (ret < 0) { + DRM_DEV_ERROR(vop->dev, "failed to get pm runtime: %d\n", ret); + return ret; +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +index 105a548d0abeb..8cecf81a5ae03 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +@@ -822,7 +822,7 @@ static void vop2_enable(struct vop2 *vop2) + { + int ret; + +- ret = pm_runtime_get_sync(vop2->dev); ++ ret = pm_runtime_resume_and_get(vop2->dev); + if (ret < 0) { + drm_err(vop2->drm, "failed to get pm runtime: %d\n", ret); + return; +diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c +index 5a284332ec49e..68f6ebb33460b 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c ++++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c +@@ -152,7 +152,7 @@ static int rk3288_lvds_poweron(struct rockchip_lvds *lvds) + DRM_DEV_ERROR(lvds->dev, "failed to enable lvds pclk %d\n", ret); + return ret; + } +- ret = pm_runtime_get_sync(lvds->dev); ++ ret = pm_runtime_resume_and_get(lvds->dev); + if (ret < 0) { + DRM_DEV_ERROR(lvds->dev, "failed to get pm runtime: %d\n", ret); + clk_disable(lvds->pclk); +@@ -336,16 +336,20 @@ static int px30_lvds_poweron(struct rockchip_lvds *lvds) + { + int ret; + +- ret = pm_runtime_get_sync(lvds->dev); ++ ret = pm_runtime_resume_and_get(lvds->dev); + if (ret < 0) { + DRM_DEV_ERROR(lvds->dev, "failed to get pm runtime: %d\n", ret); + return ret; + } + + /* Enable LVDS mode */ +- return regmap_update_bits(lvds->grf, PX30_LVDS_GRF_PD_VO_CON1, ++ ret = regmap_update_bits(lvds->grf, PX30_LVDS_GRF_PD_VO_CON1, + PX30_LVDS_MODE_EN(1) | PX30_LVDS_P2S_EN(1), + PX30_LVDS_MODE_EN(1) | PX30_LVDS_P2S_EN(1)); ++ if (ret) ++ pm_runtime_put(lvds->dev); ++ ++ return ret; + } + + static void px30_lvds_poweroff(struct rockchip_lvds *lvds) +diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c +index b6ee8a82e656c..577c477b5f467 100644 +--- a/drivers/gpu/drm/sti/sti_dvo.c ++++ b/drivers/gpu/drm/sti/sti_dvo.c +@@ -288,7 +288,7 @@ static void sti_dvo_set_mode(struct drm_bridge *bridge, + + DRM_DEBUG_DRIVER("\n"); + +- memcpy(&dvo->mode, mode, sizeof(struct drm_display_mode)); ++ drm_mode_copy(&dvo->mode, mode); + + /* According to the path used (main or aux), the dvo clocks should + * have a different parent clock. */ +@@ -346,8 +346,9 @@ static int sti_dvo_connector_get_modes(struct drm_connector *connector) + + #define CLK_TOLERANCE_HZ 50 + +-static int sti_dvo_connector_mode_valid(struct drm_connector *connector, +- struct drm_display_mode *mode) ++static enum drm_mode_status ++sti_dvo_connector_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) + { + int target = mode->clock * 1000; + int target_min = target - CLK_TOLERANCE_HZ; +diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c +index 03cc401ed5934..15097ac679314 100644 +--- a/drivers/gpu/drm/sti/sti_hda.c ++++ b/drivers/gpu/drm/sti/sti_hda.c +@@ -524,7 +524,7 @@ static void sti_hda_set_mode(struct drm_bridge *bridge, + + DRM_DEBUG_DRIVER("\n"); + +- memcpy(&hda->mode, mode, sizeof(struct drm_display_mode)); ++ drm_mode_copy(&hda->mode, mode); + + if (!hda_get_mode_idx(hda->mode, &mode_idx)) { + DRM_ERROR("Undefined mode\n"); +@@ -601,8 +601,9 @@ static int sti_hda_connector_get_modes(struct drm_connector *connector) + + #define CLK_TOLERANCE_HZ 50 + +-static int sti_hda_connector_mode_valid(struct drm_connector *connector, +- struct drm_display_mode *mode) ++static enum drm_mode_status ++sti_hda_connector_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) + { + int target = mode->clock * 1000; + int target_min = target - CLK_TOLERANCE_HZ; +diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c +index cb82622877d20..8539fe1fedc4c 100644 +--- a/drivers/gpu/drm/sti/sti_hdmi.c ++++ b/drivers/gpu/drm/sti/sti_hdmi.c +@@ -941,7 +941,7 @@ static void sti_hdmi_set_mode(struct drm_bridge *bridge, + DRM_DEBUG_DRIVER("\n"); + + /* Copy the drm display mode in the connector local structure */ +- memcpy(&hdmi->mode, mode, sizeof(struct drm_display_mode)); ++ drm_mode_copy(&hdmi->mode, mode); + + /* Update clock framerate according to the selected mode */ + ret = clk_set_rate(hdmi->clk_pix, mode->clock * 1000); +@@ -1004,8 +1004,9 @@ fail: + + #define CLK_TOLERANCE_HZ 50 + +-static int sti_hdmi_connector_mode_valid(struct drm_connector *connector, +- struct drm_display_mode *mode) ++static enum drm_mode_status ++sti_hdmi_connector_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) + { + int target = mode->clock * 1000; + int target_min = target - CLK_TOLERANCE_HZ; +diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c +index bd0f60704467f..a67453cee8832 100644 +--- a/drivers/gpu/drm/tegra/dc.c ++++ b/drivers/gpu/drm/tegra/dc.c +@@ -3205,8 +3205,10 @@ static int tegra_dc_probe(struct platform_device *pdev) + usleep_range(2000, 4000); + + err = reset_control_assert(dc->rst); +- if (err < 0) ++ if (err < 0) { ++ clk_disable_unprepare(dc->clk); + return err; ++ } + + usleep_range(2000, 4000); + +diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c +index 8275bba636119..ab125f79408f2 100644 +--- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c ++++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c +@@ -237,6 +237,10 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) + in_data->sensor_virt_addr[i] = dma_alloc_coherent(dev, sizeof(int) * 8, + &cl_data->sensor_dma_addr[i], + GFP_KERNEL); ++ if (!in_data->sensor_virt_addr[i]) { ++ rc = -ENOMEM; ++ goto cleanup; ++ } + cl_data->sensor_sts[i] = SENSOR_DISABLED; + cl_data->sensor_requested_cnt[i] = 0; + cl_data->cur_hid_dev = i; +diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c +index 6970797cdc56d..c671ce94671ca 100644 +--- a/drivers/hid/hid-apple.c ++++ b/drivers/hid/hid-apple.c +@@ -314,6 +314,7 @@ static const struct apple_key_translation swapped_option_cmd_keys[] = { + + static const struct apple_key_translation swapped_fn_leftctrl_keys[] = { + { KEY_FN, KEY_LEFTCTRL }, ++ { KEY_LEFTCTRL, KEY_FN }, + { } + }; + +@@ -375,24 +376,40 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, + struct apple_sc *asc = hid_get_drvdata(hid); + const struct apple_key_translation *trans, *table; + bool do_translate; +- u16 code = 0; ++ u16 code = usage->code; + unsigned int real_fnmode; + +- u16 fn_keycode = (swap_fn_leftctrl) ? (KEY_LEFTCTRL) : (KEY_FN); +- +- if (usage->code == fn_keycode) { +- asc->fn_on = !!value; +- input_event_with_scancode(input, usage->type, KEY_FN, +- usage->hid, value); +- return 1; +- } +- + if (fnmode == 3) { + real_fnmode = (asc->quirks & APPLE_IS_NON_APPLE) ? 2 : 1; + } else { + real_fnmode = fnmode; + } + ++ if (swap_fn_leftctrl) { ++ trans = apple_find_translation(swapped_fn_leftctrl_keys, code); ++ ++ if (trans) ++ code = trans->to; ++ } ++ ++ if (iso_layout > 0 || (iso_layout < 0 && (asc->quirks & APPLE_ISO_TILDE_QUIRK) && ++ hid->country == HID_COUNTRY_INTERNATIONAL_ISO)) { ++ trans = apple_find_translation(apple_iso_keyboard, code); ++ ++ if (trans) ++ code = trans->to; ++ } ++ ++ if (swap_opt_cmd) { ++ trans = apple_find_translation(swapped_option_cmd_keys, code); ++ ++ if (trans) ++ code = trans->to; ++ } ++ ++ if (code == KEY_FN) ++ asc->fn_on = !!value; ++ + if (real_fnmode) { + if (hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI || + hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO || +@@ -430,15 +447,18 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, + else + table = apple_fn_keys; + +- trans = apple_find_translation (table, usage->code); ++ trans = apple_find_translation(table, code); + + if (trans) { +- if (test_bit(trans->from, input->key)) ++ bool from_is_set = test_bit(trans->from, input->key); ++ bool to_is_set = test_bit(trans->to, input->key); ++ ++ if (from_is_set) + code = trans->from; +- else if (test_bit(trans->to, input->key)) ++ else if (to_is_set) + code = trans->to; + +- if (!code) { ++ if (!(from_is_set || to_is_set)) { + if (trans->flags & APPLE_FLAG_FKEY) { + switch (real_fnmode) { + case 1: +@@ -455,62 +475,31 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, + do_translate = asc->fn_on; + } + +- code = do_translate ? trans->to : trans->from; ++ if (do_translate) ++ code = trans->to; + } +- +- input_event_with_scancode(input, usage->type, code, +- usage->hid, value); +- return 1; + } + + if (asc->quirks & APPLE_NUMLOCK_EMULATION && +- (test_bit(usage->code, asc->pressed_numlock) || ++ (test_bit(code, asc->pressed_numlock) || + test_bit(LED_NUML, input->led))) { +- trans = apple_find_translation(powerbook_numlock_keys, +- usage->code); ++ trans = apple_find_translation(powerbook_numlock_keys, code); + + if (trans) { + if (value) +- set_bit(usage->code, +- asc->pressed_numlock); ++ set_bit(code, asc->pressed_numlock); + else +- clear_bit(usage->code, +- asc->pressed_numlock); ++ clear_bit(code, asc->pressed_numlock); + +- input_event_with_scancode(input, usage->type, +- trans->to, usage->hid, value); ++ code = trans->to; + } +- +- return 1; + } + } + +- if (iso_layout > 0 || (iso_layout < 0 && (asc->quirks & APPLE_ISO_TILDE_QUIRK) && +- hid->country == HID_COUNTRY_INTERNATIONAL_ISO)) { +- trans = apple_find_translation(apple_iso_keyboard, usage->code); +- if (trans) { +- input_event_with_scancode(input, usage->type, +- trans->to, usage->hid, value); +- return 1; +- } +- } +- +- if (swap_opt_cmd) { +- trans = apple_find_translation(swapped_option_cmd_keys, usage->code); +- if (trans) { +- input_event_with_scancode(input, usage->type, +- trans->to, usage->hid, value); +- return 1; +- } +- } ++ if (usage->code != code) { ++ input_event_with_scancode(input, usage->type, code, usage->hid, value); + +- if (swap_fn_leftctrl) { +- trans = apple_find_translation(swapped_fn_leftctrl_keys, usage->code); +- if (trans) { +- input_event_with_scancode(input, usage->type, +- trans->to, usage->hid, value); +- return 1; +- } ++ return 1; + } + + return 0; +@@ -640,9 +629,6 @@ static void apple_setup_input(struct input_dev *input) + apple_setup_key_translation(input, apple2021_fn_keys); + apple_setup_key_translation(input, macbookpro_no_esc_fn_keys); + apple_setup_key_translation(input, macbookpro_dedicated_esc_fn_keys); +- +- if (swap_fn_leftctrl) +- apple_setup_key_translation(input, swapped_fn_leftctrl_keys); + } + + static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi, +@@ -1011,21 +997,21 @@ static const struct hid_device_id apple_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS), + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K), +- .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, ++ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132), +- .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, ++ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680), +- .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, ++ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213), +- .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL }, ++ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K), +- .driver_data = APPLE_HAS_FN }, ++ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223), +- .driver_data = APPLE_HAS_FN }, ++ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K), +- .driver_data = APPLE_HAS_FN }, ++ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F), +- .driver_data = APPLE_HAS_FN }, ++ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 8f58c3c1bec31..e27fb27a36bfa 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -995,7 +995,10 @@ + #define USB_DEVICE_ID_ORTEK_IHOME_IMAC_A210S 0x8003 + + #define USB_VENDOR_ID_PLANTRONICS 0x047f ++#define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3210_SERIES 0xc055 + #define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3220_SERIES 0xc056 ++#define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3215_SERIES 0xc057 ++#define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3225_SERIES 0xc058 + + #define USB_VENDOR_ID_PANASONIC 0x04da + #define USB_DEVICE_ID_PANABOARD_UBT780 0x1044 +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index 859aeb07542e3..d728a94c642eb 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -340,6 +340,7 @@ static enum power_supply_property hidinput_battery_props[] = { + #define HID_BATTERY_QUIRK_PERCENT (1 << 0) /* always reports percent */ + #define HID_BATTERY_QUIRK_FEATURE (1 << 1) /* ask for feature report */ + #define HID_BATTERY_QUIRK_IGNORE (1 << 2) /* completely ignore the battery */ ++#define HID_BATTERY_QUIRK_AVOID_QUERY (1 << 3) /* do not query the battery */ + + static const struct hid_device_id hid_battery_quirks[] = { + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, +@@ -373,6 +374,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_UX550VE_TOUCHSCREEN), + HID_BATTERY_QUIRK_IGNORE }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L), ++ HID_BATTERY_QUIRK_AVOID_QUERY }, + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15), + HID_BATTERY_QUIRK_IGNORE }, + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15T_DR100), +@@ -554,6 +557,9 @@ static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, + dev->battery_avoid_query = report_type == HID_INPUT_REPORT && + field->physical == HID_DG_STYLUS; + ++ if (quirks & HID_BATTERY_QUIRK_AVOID_QUERY) ++ dev->battery_avoid_query = true; ++ + dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg); + if (IS_ERR(dev->battery)) { + error = PTR_ERR(dev->battery); +diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c +index 8a2aac18dcc51..656757c79f6b8 100644 +--- a/drivers/hid/hid-logitech-hidpp.c ++++ b/drivers/hid/hid-logitech-hidpp.c +@@ -2548,12 +2548,17 @@ static int hidpp_ff_init(struct hidpp_device *hidpp, + struct hid_device *hid = hidpp->hid_dev; + struct hid_input *hidinput; + struct input_dev *dev; +- const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor); +- const u16 bcdDevice = le16_to_cpu(udesc->bcdDevice); ++ struct usb_device_descriptor *udesc; ++ u16 bcdDevice; + struct ff_device *ff; + int error, j, num_slots = data->num_effects; + u8 version; + ++ if (!hid_is_usb(hid)) { ++ hid_err(hid, "device is not USB\n"); ++ return -ENODEV; ++ } ++ + if (list_empty(&hid->inputs)) { + hid_err(hid, "no inputs found\n"); + return -ENODEV; +@@ -2567,6 +2572,8 @@ static int hidpp_ff_init(struct hidpp_device *hidpp, + } + + /* Get firmware release */ ++ udesc = &(hid_to_usb_dev(hid)->descriptor); ++ bcdDevice = le16_to_cpu(udesc->bcdDevice); + version = bcdDevice & 255; + + /* Set supported force feedback capabilities */ +diff --git a/drivers/hid/hid-mcp2221.c b/drivers/hid/hid-mcp2221.c +index de52e9f7bb8cb..560eeec4035aa 100644 +--- a/drivers/hid/hid-mcp2221.c ++++ b/drivers/hid/hid-mcp2221.c +@@ -840,12 +840,19 @@ static int mcp2221_probe(struct hid_device *hdev, + return ret; + } + +- ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW); ++ /* ++ * This driver uses the .raw_event callback and therefore does not need any ++ * HID_CONNECT_xxx flags. ++ */ ++ ret = hid_hw_start(hdev, 0); + if (ret) { + hid_err(hdev, "can't start hardware\n"); + return ret; + } + ++ hid_info(hdev, "USB HID v%x.%02x Device [%s] on %s\n", hdev->version >> 8, ++ hdev->version & 0xff, hdev->name, hdev->phys); ++ + ret = hid_hw_open(hdev); + if (ret) { + hid_err(hdev, "can't open device\n"); +@@ -870,8 +877,7 @@ static int mcp2221_probe(struct hid_device *hdev, + mcp->adapter.retries = 1; + mcp->adapter.dev.parent = &hdev->dev; + snprintf(mcp->adapter.name, sizeof(mcp->adapter.name), +- "MCP2221 usb-i2c bridge on hidraw%d", +- ((struct hidraw *)hdev->hidraw)->minor); ++ "MCP2221 usb-i2c bridge"); + + ret = i2c_add_adapter(&mcp->adapter); + if (ret) { +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index 91a4d3fc30e08..372cbdd223e09 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -1967,6 +1967,10 @@ static const struct hid_device_id mt_devices[] = { + HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, + USB_VENDOR_ID_ELAN, 0x313a) }, + ++ { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT, ++ HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, ++ USB_VENDOR_ID_ELAN, 0x3148) }, ++ + /* Elitegroup panel */ + { .driver_data = MT_CLS_SERIAL, + MT_USB_DEVICE(USB_VENDOR_ID_ELITEGROUP, +diff --git a/drivers/hid/hid-plantronics.c b/drivers/hid/hid-plantronics.c +index e81b7cec2d124..3d414ae194acb 100644 +--- a/drivers/hid/hid-plantronics.c ++++ b/drivers/hid/hid-plantronics.c +@@ -198,9 +198,18 @@ err: + } + + static const struct hid_device_id plantronics_devices[] = { ++ { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, ++ USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3210_SERIES), ++ .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS }, + { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, + USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3220_SERIES), + .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, ++ USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3215_SERIES), ++ .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, ++ USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3225_SERIES), ++ .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS }, + { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) }, + { } + }; +diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c +index bb1f423f4ace3..84e7ba5314d3f 100644 +--- a/drivers/hid/hid-rmi.c ++++ b/drivers/hid/hid-rmi.c +@@ -326,6 +326,8 @@ static int rmi_input_event(struct hid_device *hdev, u8 *data, int size) + if (!(test_bit(RMI_STARTED, &hdata->flags))) + return 0; + ++ pm_wakeup_event(hdev->dev.parent, 0); ++ + local_irq_save(flags); + + rmi_set_attn_data(rmi_dev, data[1], &data[2], size - 2); +diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-sensor-custom.c +index 32c2306e240d6..602465ad27458 100644 +--- a/drivers/hid/hid-sensor-custom.c ++++ b/drivers/hid/hid-sensor-custom.c +@@ -62,7 +62,7 @@ struct hid_sensor_sample { + u32 raw_len; + } __packed; + +-static struct attribute hid_custom_attrs[] = { ++static struct attribute hid_custom_attrs[HID_CUSTOM_TOTAL_ATTRS] = { + {.name = "name", .mode = S_IRUGO}, + {.name = "units", .mode = S_IRUGO}, + {.name = "unit-expo", .mode = S_IRUGO}, +diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c +index 34fa991e6267e..cd1233d7e2535 100644 +--- a/drivers/hid/hid-uclogic-params.c ++++ b/drivers/hid/hid-uclogic-params.c +@@ -18,6 +18,7 @@ + #include "usbhid/usbhid.h" + #include "hid-ids.h" + #include <linux/ctype.h> ++#include <linux/string.h> + #include <asm/unaligned.h> + + /** +@@ -1211,6 +1212,69 @@ static int uclogic_params_ugee_v2_init_frame_mouse(struct uclogic_params *p) + return rc; + } + ++/** ++ * uclogic_params_ugee_v2_has_battery() - check whether a UGEE v2 device has ++ * battery or not. ++ * @hdev: The HID device of the tablet interface. ++ * ++ * Returns: ++ * True if the device has battery, false otherwise. ++ */ ++static bool uclogic_params_ugee_v2_has_battery(struct hid_device *hdev) ++{ ++ /* The XP-PEN Deco LW vendor, product and version are identical to the ++ * Deco L. The only difference reported by their firmware is the product ++ * name. Add a quirk to support battery reporting on the wireless ++ * version. ++ */ ++ if (hdev->vendor == USB_VENDOR_ID_UGEE && ++ hdev->product == USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) { ++ struct usb_device *udev = hid_to_usb_dev(hdev); ++ ++ if (strstarts(udev->product, "Deco LW")) ++ return true; ++ } ++ ++ return false; ++} ++ ++/** ++ * uclogic_params_ugee_v2_init_battery() - initialize UGEE v2 battery reporting. ++ * @hdev: The HID device of the tablet interface, cannot be NULL. ++ * @p: Parameters to fill in, cannot be NULL. ++ * ++ * Returns: ++ * Zero, if successful. A negative errno code on error. ++ */ ++static int uclogic_params_ugee_v2_init_battery(struct hid_device *hdev, ++ struct uclogic_params *p) ++{ ++ int rc = 0; ++ ++ if (!hdev || !p) ++ return -EINVAL; ++ ++ /* Some tablets contain invalid characters in hdev->uniq, throwing a ++ * "hwmon: '<name>' is not a valid name attribute, please fix" error. ++ * Use the device vendor and product IDs instead. ++ */ ++ snprintf(hdev->uniq, sizeof(hdev->uniq), "%x-%x", hdev->vendor, ++ hdev->product); ++ ++ rc = uclogic_params_frame_init_with_desc(&p->frame_list[1], ++ uclogic_rdesc_ugee_v2_battery_template_arr, ++ uclogic_rdesc_ugee_v2_battery_template_size, ++ UCLOGIC_RDESC_UGEE_V2_BATTERY_ID); ++ if (rc) ++ return rc; ++ ++ p->frame_list[1].suffix = "Battery"; ++ p->pen.subreport_list[1].value = 0xf2; ++ p->pen.subreport_list[1].id = UCLOGIC_RDESC_UGEE_V2_BATTERY_ID; ++ ++ return rc; ++} ++ + /** + * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by + * discovering their parameters. +@@ -1334,6 +1398,15 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params, + if (rc) + goto cleanup; + ++ /* Initialize the battery interface*/ ++ if (uclogic_params_ugee_v2_has_battery(hdev)) { ++ rc = uclogic_params_ugee_v2_init_battery(hdev, &p); ++ if (rc) { ++ hid_err(hdev, "error initializing battery: %d\n", rc); ++ goto cleanup; ++ } ++ } ++ + output: + /* Output parameters */ + memcpy(params, &p, sizeof(*params)); +diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c +index 6b73eb0df6bd7..fb40775f5f5b3 100644 +--- a/drivers/hid/hid-uclogic-rdesc.c ++++ b/drivers/hid/hid-uclogic-rdesc.c +@@ -1035,6 +1035,40 @@ const __u8 uclogic_rdesc_ugee_v2_frame_mouse_template_arr[] = { + const size_t uclogic_rdesc_ugee_v2_frame_mouse_template_size = + sizeof(uclogic_rdesc_ugee_v2_frame_mouse_template_arr); + ++/* Fixed report descriptor template for UGEE v2 battery reports */ ++const __u8 uclogic_rdesc_ugee_v2_battery_template_arr[] = { ++ 0x05, 0x01, /* Usage Page (Desktop), */ ++ 0x09, 0x07, /* Usage (Keypad), */ ++ 0xA1, 0x01, /* Collection (Application), */ ++ 0x85, UCLOGIC_RDESC_UGEE_V2_BATTERY_ID, ++ /* Report ID, */ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x95, 0x02, /* Report Count (2), */ ++ 0x81, 0x01, /* Input (Constant), */ ++ 0x05, 0x84, /* Usage Page (Power Device), */ ++ 0x05, 0x85, /* Usage Page (Battery System), */ ++ 0x09, 0x65, /* Usage Page (AbsoluteStateOfCharge), */ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x95, 0x01, /* Report Count (1), */ ++ 0x15, 0x00, /* Logical Minimum (0), */ ++ 0x26, 0xff, 0x00, /* Logical Maximum (255), */ ++ 0x81, 0x02, /* Input (Variable), */ ++ 0x75, 0x01, /* Report Size (1), */ ++ 0x95, 0x01, /* Report Count (1), */ ++ 0x15, 0x00, /* Logical Minimum (0), */ ++ 0x25, 0x01, /* Logical Maximum (1), */ ++ 0x09, 0x44, /* Usage Page (Charging), */ ++ 0x81, 0x02, /* Input (Variable), */ ++ 0x95, 0x07, /* Report Count (7), */ ++ 0x81, 0x01, /* Input (Constant), */ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x95, 0x07, /* Report Count (7), */ ++ 0x81, 0x01, /* Input (Constant), */ ++ 0xC0 /* End Collection */ ++}; ++const size_t uclogic_rdesc_ugee_v2_battery_template_size = ++ sizeof(uclogic_rdesc_ugee_v2_battery_template_arr); ++ + /* Fixed report descriptor for Ugee EX07 frame */ + const __u8 uclogic_rdesc_ugee_ex07_frame_arr[] = { + 0x05, 0x01, /* Usage Page (Desktop), */ +diff --git a/drivers/hid/hid-uclogic-rdesc.h b/drivers/hid/hid-uclogic-rdesc.h +index 0502a06564964..a1f78c07293ff 100644 +--- a/drivers/hid/hid-uclogic-rdesc.h ++++ b/drivers/hid/hid-uclogic-rdesc.h +@@ -161,6 +161,9 @@ extern const size_t uclogic_rdesc_v2_frame_dial_size; + /* Device ID byte offset in v2 frame dial reports */ + #define UCLOGIC_RDESC_V2_FRAME_DIAL_DEV_ID_BYTE 0x4 + ++/* Report ID for tweaked UGEE v2 battery reports */ ++#define UCLOGIC_RDESC_UGEE_V2_BATTERY_ID 0xba ++ + /* Fixed report descriptor template for UGEE v2 pen reports */ + extern const __u8 uclogic_rdesc_ugee_v2_pen_template_arr[]; + extern const size_t uclogic_rdesc_ugee_v2_pen_template_size; +@@ -177,6 +180,10 @@ extern const size_t uclogic_rdesc_ugee_v2_frame_dial_template_size; + extern const __u8 uclogic_rdesc_ugee_v2_frame_mouse_template_arr[]; + extern const size_t uclogic_rdesc_ugee_v2_frame_mouse_template_size; + ++/* Fixed report descriptor template for UGEE v2 battery reports */ ++extern const __u8 uclogic_rdesc_ugee_v2_battery_template_arr[]; ++extern const size_t uclogic_rdesc_ugee_v2_battery_template_size; ++ + /* Fixed report descriptor for Ugee EX07 frame */ + extern const __u8 uclogic_rdesc_ugee_ex07_frame_arr[]; + extern const size_t uclogic_rdesc_ugee_ex07_frame_size; +diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c +index 0667b6022c3b7..a9428b7f34a46 100644 +--- a/drivers/hid/i2c-hid/i2c-hid-core.c ++++ b/drivers/hid/i2c-hid/i2c-hid-core.c +@@ -554,7 +554,8 @@ static void i2c_hid_get_input(struct i2c_hid *ihid) + i2c_hid_dbg(ihid, "input: %*ph\n", ret_size, ihid->inbuf); + + if (test_bit(I2C_HID_STARTED, &ihid->flags)) { +- pm_wakeup_event(&ihid->client->dev, 0); ++ if (ihid->hid->group != HID_GROUP_RMI) ++ pm_wakeup_event(&ihid->client->dev, 0); + + hid_input_report(ihid->hid, HID_INPUT_REPORT, + ihid->inbuf + sizeof(__le16), +diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c +index 634263e4556b0..fb538a6c4add8 100644 +--- a/drivers/hid/wacom_sys.c ++++ b/drivers/hid/wacom_sys.c +@@ -155,6 +155,9 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, + { + struct wacom *wacom = hid_get_drvdata(hdev); + ++ if (wacom->wacom_wac.features.type == BOOTLOADER) ++ return 0; ++ + if (size > WACOM_PKGLEN_MAX) + return 1; + +@@ -2785,6 +2788,11 @@ static int wacom_probe(struct hid_device *hdev, + return error; + } + ++ if (features->type == BOOTLOADER) { ++ hid_warn(hdev, "Using device in hidraw-only mode"); ++ return hid_hw_start(hdev, HID_CONNECT_HIDRAW); ++ } ++ + error = wacom_parse_and_register(wacom, false); + if (error) + return error; +diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c +index 0f3d57b426846..9312d611db8e5 100644 +--- a/drivers/hid/wacom_wac.c ++++ b/drivers/hid/wacom_wac.c +@@ -4882,6 +4882,9 @@ static const struct wacom_features wacom_features_0x3dd = + static const struct wacom_features wacom_features_HID_ANY_ID = + { "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID }; + ++static const struct wacom_features wacom_features_0x94 = ++ { "Wacom Bootloader", .type = BOOTLOADER }; ++ + #define USB_DEVICE_WACOM(prod) \ + HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\ + .driver_data = (kernel_ulong_t)&wacom_features_##prod +@@ -4955,6 +4958,7 @@ const struct hid_device_id wacom_ids[] = { + { USB_DEVICE_WACOM(0x84) }, + { USB_DEVICE_WACOM(0x90) }, + { USB_DEVICE_WACOM(0x93) }, ++ { USB_DEVICE_WACOM(0x94) }, + { USB_DEVICE_WACOM(0x97) }, + { USB_DEVICE_WACOM(0x9A) }, + { USB_DEVICE_WACOM(0x9F) }, +diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h +index 5ca6c06d143be..16f221388563d 100644 +--- a/drivers/hid/wacom_wac.h ++++ b/drivers/hid/wacom_wac.h +@@ -243,6 +243,7 @@ enum { + MTTPC, + MTTPC_B, + HID_GENERIC, ++ BOOTLOADER, + MAX_TYPE + }; + +diff --git a/drivers/hsi/controllers/omap_ssi_core.c b/drivers/hsi/controllers/omap_ssi_core.c +index eb98201583185..26f2c3c012978 100644 +--- a/drivers/hsi/controllers/omap_ssi_core.c ++++ b/drivers/hsi/controllers/omap_ssi_core.c +@@ -502,8 +502,10 @@ static int ssi_probe(struct platform_device *pd) + platform_set_drvdata(pd, ssi); + + err = ssi_add_controller(ssi, pd); +- if (err < 0) ++ if (err < 0) { ++ hsi_put_controller(ssi); + goto out1; ++ } + + pm_runtime_enable(&pd->dev); + +@@ -536,9 +538,9 @@ out3: + device_for_each_child(&pd->dev, NULL, ssi_remove_ports); + out2: + ssi_remove_controller(ssi); ++ pm_runtime_disable(&pd->dev); + out1: + platform_set_drvdata(pd, NULL); +- pm_runtime_disable(&pd->dev); + + return err; + } +@@ -629,7 +631,13 @@ static int __init ssi_init(void) { + if (ret) + return ret; + +- return platform_driver_register(&ssi_port_pdriver); ++ ret = platform_driver_register(&ssi_port_pdriver); ++ if (ret) { ++ platform_driver_unregister(&ssi_pdriver); ++ return ret; ++ } ++ ++ return 0; + } + module_init(ssi_init); + +diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c +index 59a4aa86d1f35..c6692fd5ab155 100644 +--- a/drivers/hv/ring_buffer.c ++++ b/drivers/hv/ring_buffer.c +@@ -280,6 +280,19 @@ void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info) + ring_info->pkt_buffer_size = 0; + } + ++/* ++ * Check if the ring buffer spinlock is available to take or not; used on ++ * atomic contexts, like panic path (see the Hyper-V framebuffer driver). ++ */ ++ ++bool hv_ringbuffer_spinlock_busy(struct vmbus_channel *channel) ++{ ++ struct hv_ring_buffer_info *rinfo = &channel->outbound; ++ ++ return spin_is_locked(&rinfo->ring_lock); ++} ++EXPORT_SYMBOL_GPL(hv_ringbuffer_spinlock_busy); ++ + /* Write to the ring buffer. */ + int hv_ringbuffer_write(struct vmbus_channel *channel, + const struct kvec *kv_list, u32 kv_count, +diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig +index 7ac3daaf59ce0..d3bccc8176c51 100644 +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -799,6 +799,7 @@ config SENSORS_IT87 + config SENSORS_JC42 + tristate "JEDEC JC42.4 compliant memory module temperature sensors" + depends on I2C ++ select REGMAP_I2C + help + If you say yes here, you get support for JEDEC JC42.4 compliant + temperature sensors, which are used on many DDR3 memory modules for +diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c +index aa1f25add0b6b..e42ae43f3de46 100644 +--- a/drivers/hwmon/emc2305.c ++++ b/drivers/hwmon/emc2305.c +@@ -16,7 +16,6 @@ static const unsigned short + emc2305_normal_i2c[] = { 0x27, 0x2c, 0x2d, 0x2e, 0x2f, 0x4c, 0x4d, I2C_CLIENT_END }; + + #define EMC2305_REG_DRIVE_FAIL_STATUS 0x27 +-#define EMC2305_REG_DEVICE 0xfd + #define EMC2305_REG_VENDOR 0xfe + #define EMC2305_FAN_MAX 0xff + #define EMC2305_FAN_MIN 0x00 +@@ -172,22 +171,12 @@ static int emc2305_get_max_state(struct thermal_cooling_device *cdev, unsigned l + return 0; + } + +-static int emc2305_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) ++static int __emc2305_set_cur_state(struct emc2305_data *data, int cdev_idx, unsigned long state) + { +- int cdev_idx, ret; +- struct emc2305_data *data = cdev->devdata; ++ int ret; + struct i2c_client *client = data->client; + u8 val, i; + +- if (state > data->max_state) +- return -EINVAL; +- +- cdev_idx = emc2305_get_cdev_idx(cdev); +- if (cdev_idx < 0) +- return cdev_idx; +- +- /* Save thermal state. */ +- data->cdev_data[cdev_idx].last_thermal_state = state; + state = max_t(unsigned long, state, data->cdev_data[cdev_idx].last_hwmon_state); + + val = EMC2305_PWM_STATE2DUTY(state, data->max_state, EMC2305_FAN_MAX); +@@ -212,6 +201,27 @@ static int emc2305_set_cur_state(struct thermal_cooling_device *cdev, unsigned l + return 0; + } + ++static int emc2305_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) ++{ ++ int cdev_idx, ret; ++ struct emc2305_data *data = cdev->devdata; ++ ++ if (state > data->max_state) ++ return -EINVAL; ++ ++ cdev_idx = emc2305_get_cdev_idx(cdev); ++ if (cdev_idx < 0) ++ return cdev_idx; ++ ++ /* Save thermal state. */ ++ data->cdev_data[cdev_idx].last_thermal_state = state; ++ ret = __emc2305_set_cur_state(data, cdev_idx, state); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ + static const struct thermal_cooling_device_ops emc2305_cooling_ops = { + .get_max_state = emc2305_get_max_state, + .get_cur_state = emc2305_get_cur_state, +@@ -402,7 +412,7 @@ emc2305_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int ch + */ + if (data->cdev_data[cdev_idx].last_hwmon_state >= + data->cdev_data[cdev_idx].last_thermal_state) +- return emc2305_set_cur_state(data->cdev_data[cdev_idx].cdev, ++ return __emc2305_set_cur_state(data, cdev_idx, + data->cdev_data[cdev_idx].last_hwmon_state); + return 0; + } +@@ -524,7 +534,7 @@ static int emc2305_probe(struct i2c_client *client, const struct i2c_device_id * + struct device *dev = &client->dev; + struct emc2305_data *data; + struct emc2305_platform_data *pdata; +- int vendor, device; ++ int vendor; + int ret; + int i; + +@@ -535,10 +545,6 @@ static int emc2305_probe(struct i2c_client *client, const struct i2c_device_id * + if (vendor != EMC2305_VENDOR) + return -ENODEV; + +- device = i2c_smbus_read_byte_data(client, EMC2305_REG_DEVICE); +- if (device != EMC2305_DEVICE) +- return -ENODEV; +- + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; +diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c +index 30888feaf589b..6593d81cb901b 100644 +--- a/drivers/hwmon/jc42.c ++++ b/drivers/hwmon/jc42.c +@@ -19,6 +19,7 @@ + #include <linux/err.h> + #include <linux/mutex.h> + #include <linux/of.h> ++#include <linux/regmap.h> + + /* Addresses to scan */ + static const unsigned short normal_i2c[] = { +@@ -199,31 +200,14 @@ static struct jc42_chips jc42_chips[] = { + { STM_MANID, STTS3000_DEVID, STTS3000_DEVID_MASK }, + }; + +-enum temp_index { +- t_input = 0, +- t_crit, +- t_min, +- t_max, +- t_num_temp +-}; +- +-static const u8 temp_regs[t_num_temp] = { +- [t_input] = JC42_REG_TEMP, +- [t_crit] = JC42_REG_TEMP_CRITICAL, +- [t_min] = JC42_REG_TEMP_LOWER, +- [t_max] = JC42_REG_TEMP_UPPER, +-}; +- + /* Each client has this additional data */ + struct jc42_data { +- struct i2c_client *client; + struct mutex update_lock; /* protect register access */ ++ struct regmap *regmap; + bool extended; /* true if extended range supported */ + bool valid; +- unsigned long last_updated; /* In jiffies */ + u16 orig_config; /* original configuration */ + u16 config; /* current configuration */ +- u16 temp[t_num_temp];/* Temperatures */ + }; + + #define JC42_TEMP_MIN_EXTENDED (-40000) +@@ -248,85 +232,102 @@ static int jc42_temp_from_reg(s16 reg) + return reg * 125 / 2; + } + +-static struct jc42_data *jc42_update_device(struct device *dev) +-{ +- struct jc42_data *data = dev_get_drvdata(dev); +- struct i2c_client *client = data->client; +- struct jc42_data *ret = data; +- int i, val; +- +- mutex_lock(&data->update_lock); +- +- if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { +- for (i = 0; i < t_num_temp; i++) { +- val = i2c_smbus_read_word_swapped(client, temp_regs[i]); +- if (val < 0) { +- ret = ERR_PTR(val); +- goto abort; +- } +- data->temp[i] = val; +- } +- data->last_updated = jiffies; +- data->valid = true; +- } +-abort: +- mutex_unlock(&data->update_lock); +- return ret; +-} +- + static int jc42_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) + { +- struct jc42_data *data = jc42_update_device(dev); +- int temp, hyst; ++ struct jc42_data *data = dev_get_drvdata(dev); ++ unsigned int regval; ++ int ret, temp, hyst; + +- if (IS_ERR(data)) +- return PTR_ERR(data); ++ mutex_lock(&data->update_lock); + + switch (attr) { + case hwmon_temp_input: +- *val = jc42_temp_from_reg(data->temp[t_input]); +- return 0; ++ ret = regmap_read(data->regmap, JC42_REG_TEMP, ®val); ++ if (ret) ++ break; ++ ++ *val = jc42_temp_from_reg(regval); ++ break; + case hwmon_temp_min: +- *val = jc42_temp_from_reg(data->temp[t_min]); +- return 0; ++ ret = regmap_read(data->regmap, JC42_REG_TEMP_LOWER, ®val); ++ if (ret) ++ break; ++ ++ *val = jc42_temp_from_reg(regval); ++ break; + case hwmon_temp_max: +- *val = jc42_temp_from_reg(data->temp[t_max]); +- return 0; ++ ret = regmap_read(data->regmap, JC42_REG_TEMP_UPPER, ®val); ++ if (ret) ++ break; ++ ++ *val = jc42_temp_from_reg(regval); ++ break; + case hwmon_temp_crit: +- *val = jc42_temp_from_reg(data->temp[t_crit]); +- return 0; ++ ret = regmap_read(data->regmap, JC42_REG_TEMP_CRITICAL, ++ ®val); ++ if (ret) ++ break; ++ ++ *val = jc42_temp_from_reg(regval); ++ break; + case hwmon_temp_max_hyst: +- temp = jc42_temp_from_reg(data->temp[t_max]); ++ ret = regmap_read(data->regmap, JC42_REG_TEMP_UPPER, ®val); ++ if (ret) ++ break; ++ ++ temp = jc42_temp_from_reg(regval); + hyst = jc42_hysteresis[(data->config & JC42_CFG_HYST_MASK) + >> JC42_CFG_HYST_SHIFT]; + *val = temp - hyst; +- return 0; ++ break; + case hwmon_temp_crit_hyst: +- temp = jc42_temp_from_reg(data->temp[t_crit]); ++ ret = regmap_read(data->regmap, JC42_REG_TEMP_CRITICAL, ++ ®val); ++ if (ret) ++ break; ++ ++ temp = jc42_temp_from_reg(regval); + hyst = jc42_hysteresis[(data->config & JC42_CFG_HYST_MASK) + >> JC42_CFG_HYST_SHIFT]; + *val = temp - hyst; +- return 0; ++ break; + case hwmon_temp_min_alarm: +- *val = (data->temp[t_input] >> JC42_ALARM_MIN_BIT) & 1; +- return 0; ++ ret = regmap_read(data->regmap, JC42_REG_TEMP, ®val); ++ if (ret) ++ break; ++ ++ *val = (regval >> JC42_ALARM_MIN_BIT) & 1; ++ break; + case hwmon_temp_max_alarm: +- *val = (data->temp[t_input] >> JC42_ALARM_MAX_BIT) & 1; +- return 0; ++ ret = regmap_read(data->regmap, JC42_REG_TEMP, ®val); ++ if (ret) ++ break; ++ ++ *val = (regval >> JC42_ALARM_MAX_BIT) & 1; ++ break; + case hwmon_temp_crit_alarm: +- *val = (data->temp[t_input] >> JC42_ALARM_CRIT_BIT) & 1; +- return 0; ++ ret = regmap_read(data->regmap, JC42_REG_TEMP, ®val); ++ if (ret) ++ break; ++ ++ *val = (regval >> JC42_ALARM_CRIT_BIT) & 1; ++ break; + default: +- return -EOPNOTSUPP; ++ ret = -EOPNOTSUPP; ++ break; + } ++ ++ mutex_unlock(&data->update_lock); ++ ++ return ret; + } + + static int jc42_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long val) + { + struct jc42_data *data = dev_get_drvdata(dev); +- struct i2c_client *client = data->client; ++ unsigned int regval; + int diff, hyst; + int ret; + +@@ -334,21 +335,23 @@ static int jc42_write(struct device *dev, enum hwmon_sensor_types type, + + switch (attr) { + case hwmon_temp_min: +- data->temp[t_min] = jc42_temp_to_reg(val, data->extended); +- ret = i2c_smbus_write_word_swapped(client, temp_regs[t_min], +- data->temp[t_min]); ++ ret = regmap_write(data->regmap, JC42_REG_TEMP_LOWER, ++ jc42_temp_to_reg(val, data->extended)); + break; + case hwmon_temp_max: +- data->temp[t_max] = jc42_temp_to_reg(val, data->extended); +- ret = i2c_smbus_write_word_swapped(client, temp_regs[t_max], +- data->temp[t_max]); ++ ret = regmap_write(data->regmap, JC42_REG_TEMP_UPPER, ++ jc42_temp_to_reg(val, data->extended)); + break; + case hwmon_temp_crit: +- data->temp[t_crit] = jc42_temp_to_reg(val, data->extended); +- ret = i2c_smbus_write_word_swapped(client, temp_regs[t_crit], +- data->temp[t_crit]); ++ ret = regmap_write(data->regmap, JC42_REG_TEMP_CRITICAL, ++ jc42_temp_to_reg(val, data->extended)); + break; + case hwmon_temp_crit_hyst: ++ ret = regmap_read(data->regmap, JC42_REG_TEMP_CRITICAL, ++ ®val); ++ if (ret) ++ break; ++ + /* + * JC42.4 compliant chips only support four hysteresis values. + * Pick best choice and go from there. +@@ -356,7 +359,7 @@ static int jc42_write(struct device *dev, enum hwmon_sensor_types type, + val = clamp_val(val, (data->extended ? JC42_TEMP_MIN_EXTENDED + : JC42_TEMP_MIN) - 6000, + JC42_TEMP_MAX); +- diff = jc42_temp_from_reg(data->temp[t_crit]) - val; ++ diff = jc42_temp_from_reg(regval) - val; + hyst = 0; + if (diff > 0) { + if (diff < 2250) +@@ -368,9 +371,8 @@ static int jc42_write(struct device *dev, enum hwmon_sensor_types type, + } + data->config = (data->config & ~JC42_CFG_HYST_MASK) | + (hyst << JC42_CFG_HYST_SHIFT); +- ret = i2c_smbus_write_word_swapped(data->client, +- JC42_REG_CONFIG, +- data->config); ++ ret = regmap_write(data->regmap, JC42_REG_CONFIG, ++ data->config); + break; + default: + ret = -EOPNOTSUPP; +@@ -470,51 +472,80 @@ static const struct hwmon_chip_info jc42_chip_info = { + .info = jc42_info, + }; + ++static bool jc42_readable_reg(struct device *dev, unsigned int reg) ++{ ++ return (reg >= JC42_REG_CAP && reg <= JC42_REG_DEVICEID) || ++ reg == JC42_REG_SMBUS; ++} ++ ++static bool jc42_writable_reg(struct device *dev, unsigned int reg) ++{ ++ return (reg >= JC42_REG_CONFIG && reg <= JC42_REG_TEMP_CRITICAL) || ++ reg == JC42_REG_SMBUS; ++} ++ ++static bool jc42_volatile_reg(struct device *dev, unsigned int reg) ++{ ++ return reg == JC42_REG_CONFIG || reg == JC42_REG_TEMP; ++} ++ ++static const struct regmap_config jc42_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 16, ++ .val_format_endian = REGMAP_ENDIAN_BIG, ++ .max_register = JC42_REG_SMBUS, ++ .writeable_reg = jc42_writable_reg, ++ .readable_reg = jc42_readable_reg, ++ .volatile_reg = jc42_volatile_reg, ++ .cache_type = REGCACHE_RBTREE, ++}; ++ + static int jc42_probe(struct i2c_client *client) + { + struct device *dev = &client->dev; + struct device *hwmon_dev; ++ unsigned int config, cap; + struct jc42_data *data; +- int config, cap; ++ int ret; + + data = devm_kzalloc(dev, sizeof(struct jc42_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + +- data->client = client; ++ data->regmap = devm_regmap_init_i2c(client, &jc42_regmap_config); ++ if (IS_ERR(data->regmap)) ++ return PTR_ERR(data->regmap); ++ + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + +- cap = i2c_smbus_read_word_swapped(client, JC42_REG_CAP); +- if (cap < 0) +- return cap; ++ ret = regmap_read(data->regmap, JC42_REG_CAP, &cap); ++ if (ret) ++ return ret; + + data->extended = !!(cap & JC42_CAP_RANGE); + + if (device_property_read_bool(dev, "smbus-timeout-disable")) { +- int smbus; +- + /* + * Not all chips support this register, but from a + * quick read of various datasheets no chip appears + * incompatible with the below attempt to disable + * the timeout. And the whole thing is opt-in... + */ +- smbus = i2c_smbus_read_word_swapped(client, JC42_REG_SMBUS); +- if (smbus < 0) +- return smbus; +- i2c_smbus_write_word_swapped(client, JC42_REG_SMBUS, +- smbus | SMBUS_STMOUT); ++ ret = regmap_set_bits(data->regmap, JC42_REG_SMBUS, ++ SMBUS_STMOUT); ++ if (ret) ++ return ret; + } + +- config = i2c_smbus_read_word_swapped(client, JC42_REG_CONFIG); +- if (config < 0) +- return config; ++ ret = regmap_read(data->regmap, JC42_REG_CONFIG, &config); ++ if (ret) ++ return ret; + + data->orig_config = config; + if (config & JC42_CFG_SHUTDOWN) { + config &= ~JC42_CFG_SHUTDOWN; +- i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, config); ++ regmap_write(data->regmap, JC42_REG_CONFIG, config); + } + data->config = config; + +@@ -535,7 +566,7 @@ static void jc42_remove(struct i2c_client *client) + + config = (data->orig_config & ~JC42_CFG_HYST_MASK) + | (data->config & JC42_CFG_HYST_MASK); +- i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, config); ++ regmap_write(data->regmap, JC42_REG_CONFIG, config); + } + } + +@@ -546,8 +577,11 @@ static int jc42_suspend(struct device *dev) + struct jc42_data *data = dev_get_drvdata(dev); + + data->config |= JC42_CFG_SHUTDOWN; +- i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG, +- data->config); ++ regmap_write(data->regmap, JC42_REG_CONFIG, data->config); ++ ++ regcache_cache_only(data->regmap, true); ++ regcache_mark_dirty(data->regmap); ++ + return 0; + } + +@@ -555,10 +589,13 @@ static int jc42_resume(struct device *dev) + { + struct jc42_data *data = dev_get_drvdata(dev); + ++ regcache_cache_only(data->regmap, false); ++ + data->config &= ~JC42_CFG_SHUTDOWN; +- i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG, +- data->config); +- return 0; ++ regmap_write(data->regmap, JC42_REG_CONFIG, data->config); ++ ++ /* Restore cached register values to hardware */ ++ return regcache_sync(data->regmap); + } + + static const struct dev_pm_ops jc42_dev_pm_ops = { +diff --git a/drivers/hwmon/nct6775-platform.c b/drivers/hwmon/nct6775-platform.c +index b347837842139..bf43f73dc835f 100644 +--- a/drivers/hwmon/nct6775-platform.c ++++ b/drivers/hwmon/nct6775-platform.c +@@ -1043,7 +1043,9 @@ static struct platform_device *pdev[2]; + + static const char * const asus_wmi_boards[] = { + "PRO H410T", ++ "ProArt B550-CREATOR", + "ProArt X570-CREATOR WIFI", ++ "ProArt Z490-CREATOR 10G", + "Pro B550M-C", + "Pro WS X570-ACE", + "PRIME B360-PLUS", +@@ -1055,8 +1057,10 @@ static const char * const asus_wmi_boards[] = { + "PRIME X570-P", + "PRIME X570-PRO", + "ROG CROSSHAIR VIII DARK HERO", ++ "ROG CROSSHAIR VIII EXTREME", + "ROG CROSSHAIR VIII FORMULA", + "ROG CROSSHAIR VIII HERO", ++ "ROG CROSSHAIR VIII HERO (WI-FI)", + "ROG CROSSHAIR VIII IMPACT", + "ROG STRIX B550-A GAMING", + "ROG STRIX B550-E GAMING", +@@ -1080,8 +1084,11 @@ static const char * const asus_wmi_boards[] = { + "ROG STRIX Z490-G GAMING (WI-FI)", + "ROG STRIX Z490-H GAMING", + "ROG STRIX Z490-I GAMING", ++ "TUF GAMING B550M-E", ++ "TUF GAMING B550M-E (WI-FI)", + "TUF GAMING B550M-PLUS", + "TUF GAMING B550M-PLUS (WI-FI)", ++ "TUF GAMING B550M-PLUS WIFI II", + "TUF GAMING B550-PLUS", + "TUF GAMING B550-PLUS WIFI II", + "TUF GAMING B550-PRO", +diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c +index c6e8c6542f24b..d2cf4f4848e1b 100644 +--- a/drivers/hwtracing/coresight/coresight-cti-core.c ++++ b/drivers/hwtracing/coresight/coresight-cti-core.c +@@ -564,7 +564,7 @@ static void cti_add_assoc_to_csdev(struct coresight_device *csdev) + * if we found a matching csdev then update the ECT + * association pointer for the device with this CTI. + */ +- coresight_set_assoc_ectdev_mutex(csdev->ect_dev, ++ coresight_set_assoc_ectdev_mutex(csdev, + ect_item->csdev); + break; + } +diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c +index 2b386bb848f8d..1fc4fd79a1c69 100644 +--- a/drivers/hwtracing/coresight/coresight-trbe.c ++++ b/drivers/hwtracing/coresight/coresight-trbe.c +@@ -1434,6 +1434,7 @@ static int arm_trbe_probe_cpuhp(struct trbe_drvdata *drvdata) + + static void arm_trbe_remove_cpuhp(struct trbe_drvdata *drvdata) + { ++ cpuhp_state_remove_instance(drvdata->trbe_online, &drvdata->hotplug_node); + cpuhp_remove_multi_state(drvdata->trbe_online); + } + +diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c +index fe2349590f75e..c74985d77b0ec 100644 +--- a/drivers/i2c/busses/i2c-ismt.c ++++ b/drivers/i2c/busses/i2c-ismt.c +@@ -509,6 +509,9 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, + if (read_write == I2C_SMBUS_WRITE) { + /* Block Write */ + dev_dbg(dev, "I2C_SMBUS_BLOCK_DATA: WRITE\n"); ++ if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX) ++ return -EINVAL; ++ + dma_size = data->block[0] + 1; + dma_direction = DMA_TO_DEVICE; + desc->wr_len_cmd = dma_size; +diff --git a/drivers/i2c/busses/i2c-pxa-pci.c b/drivers/i2c/busses/i2c-pxa-pci.c +index f614cade432bb..30e38bc8b6db8 100644 +--- a/drivers/i2c/busses/i2c-pxa-pci.c ++++ b/drivers/i2c/busses/i2c-pxa-pci.c +@@ -105,7 +105,7 @@ static int ce4100_i2c_probe(struct pci_dev *dev, + int i; + struct ce4100_devices *sds; + +- ret = pci_enable_device_mem(dev); ++ ret = pcim_enable_device(dev); + if (ret) + return ret; + +@@ -114,10 +114,8 @@ static int ce4100_i2c_probe(struct pci_dev *dev, + return -EINVAL; + } + sds = kzalloc(sizeof(*sds), GFP_KERNEL); +- if (!sds) { +- ret = -ENOMEM; +- goto err_mem; +- } ++ if (!sds) ++ return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(sds->pdev); i++) { + sds->pdev[i] = add_i2c_device(dev, i); +@@ -133,8 +131,6 @@ static int ce4100_i2c_probe(struct pci_dev *dev, + + err_dev_add: + kfree(sds); +-err_mem: +- pci_disable_device(dev); + return ret; + } + +diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c +index 0e0679f65cf77..30a6de1694e07 100644 +--- a/drivers/i2c/muxes/i2c-mux-reg.c ++++ b/drivers/i2c/muxes/i2c-mux-reg.c +@@ -183,13 +183,12 @@ static int i2c_mux_reg_probe(struct platform_device *pdev) + if (!mux->data.reg) { + dev_info(&pdev->dev, + "Register not set, using platform resource\n"); +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- mux->data.reg_size = resource_size(res); +- mux->data.reg = devm_ioremap_resource(&pdev->dev, res); ++ mux->data.reg = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(mux->data.reg)) { + ret = PTR_ERR(mux->data.reg); + goto err_put_parent; + } ++ mux->data.reg_size = resource_size(res); + } + + if (mux->data.reg_size != 4 && mux->data.reg_size != 2 && +diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c +index 261a9a6b45e15..d8570f620785a 100644 +--- a/drivers/iio/adc/ad_sigma_delta.c ++++ b/drivers/iio/adc/ad_sigma_delta.c +@@ -281,10 +281,10 @@ int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev, + unsigned int data_reg; + int ret = 0; + +- if (iio_buffer_enabled(indio_dev)) +- return -EBUSY; ++ ret = iio_device_claim_direct_mode(indio_dev); ++ if (ret) ++ return ret; + +- mutex_lock(&indio_dev->mlock); + ad_sigma_delta_set_channel(sigma_delta, chan->address); + + spi_bus_lock(sigma_delta->spi->master); +@@ -323,7 +323,7 @@ out: + ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE); + sigma_delta->bus_locked = false; + spi_bus_unlock(sigma_delta->spi->master); +- mutex_unlock(&indio_dev->mlock); ++ iio_device_release_direct_mode(indio_dev); + + if (ret) + return ret; +diff --git a/drivers/iio/adc/ti-adc128s052.c b/drivers/iio/adc/ti-adc128s052.c +index 622fd384983c7..b3d5b9b7255bc 100644 +--- a/drivers/iio/adc/ti-adc128s052.c ++++ b/drivers/iio/adc/ti-adc128s052.c +@@ -181,13 +181,13 @@ static int adc128_probe(struct spi_device *spi) + } + + static const struct of_device_id adc128_of_match[] = { +- { .compatible = "ti,adc128s052", }, +- { .compatible = "ti,adc122s021", }, +- { .compatible = "ti,adc122s051", }, +- { .compatible = "ti,adc122s101", }, +- { .compatible = "ti,adc124s021", }, +- { .compatible = "ti,adc124s051", }, +- { .compatible = "ti,adc124s101", }, ++ { .compatible = "ti,adc128s052", .data = (void*)0L, }, ++ { .compatible = "ti,adc122s021", .data = (void*)1L, }, ++ { .compatible = "ti,adc122s051", .data = (void*)1L, }, ++ { .compatible = "ti,adc122s101", .data = (void*)1L, }, ++ { .compatible = "ti,adc124s021", .data = (void*)2L, }, ++ { .compatible = "ti,adc124s051", .data = (void*)2L, }, ++ { .compatible = "ti,adc124s101", .data = (void*)2L, }, + { /* sentinel */ }, + }; + MODULE_DEVICE_TABLE(of, adc128_of_match); +diff --git a/drivers/iio/addac/ad74413r.c b/drivers/iio/addac/ad74413r.c +index 899bcd83f40bc..e0e130ba9d3ec 100644 +--- a/drivers/iio/addac/ad74413r.c ++++ b/drivers/iio/addac/ad74413r.c +@@ -691,7 +691,7 @@ static int ad74413_get_input_current_offset(struct ad74413r_state *st, + if (ret) + return ret; + +- *val = voltage_offset * AD74413R_ADC_RESULT_MAX / voltage_range; ++ *val = voltage_offset * (int)AD74413R_ADC_RESULT_MAX / voltage_range; + + return IIO_VAL_INT; + } +diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c +index f7fcfd04f659d..bc40240b29e26 100644 +--- a/drivers/iio/imu/adis.c ++++ b/drivers/iio/imu/adis.c +@@ -270,23 +270,19 @@ EXPORT_SYMBOL_NS(adis_debugfs_reg_access, IIO_ADISLIB); + #endif + + /** +- * adis_enable_irq() - Enable or disable data ready IRQ ++ * __adis_enable_irq() - Enable or disable data ready IRQ (unlocked) + * @adis: The adis device + * @enable: Whether to enable the IRQ + * + * Returns 0 on success, negative error code otherwise + */ +-int adis_enable_irq(struct adis *adis, bool enable) ++int __adis_enable_irq(struct adis *adis, bool enable) + { +- int ret = 0; ++ int ret; + u16 msc; + +- mutex_lock(&adis->state_lock); +- +- if (adis->data->enable_irq) { +- ret = adis->data->enable_irq(adis, enable); +- goto out_unlock; +- } ++ if (adis->data->enable_irq) ++ return adis->data->enable_irq(adis, enable); + + if (adis->data->unmasked_drdy) { + if (enable) +@@ -294,12 +290,12 @@ int adis_enable_irq(struct adis *adis, bool enable) + else + disable_irq(adis->spi->irq); + +- goto out_unlock; ++ return 0; + } + + ret = __adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc); + if (ret) +- goto out_unlock; ++ return ret; + + msc |= ADIS_MSC_CTRL_DATA_RDY_POL_HIGH; + msc &= ~ADIS_MSC_CTRL_DATA_RDY_DIO2; +@@ -308,13 +304,9 @@ int adis_enable_irq(struct adis *adis, bool enable) + else + msc &= ~ADIS_MSC_CTRL_DATA_RDY_EN; + +- ret = __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc); +- +-out_unlock: +- mutex_unlock(&adis->state_lock); +- return ret; ++ return __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc); + } +-EXPORT_SYMBOL_NS(adis_enable_irq, IIO_ADISLIB); ++EXPORT_SYMBOL_NS(__adis_enable_irq, IIO_ADISLIB); + + /** + * __adis_check_status() - Check the device for error conditions (unlocked) +@@ -445,7 +437,7 @@ int __adis_initial_startup(struct adis *adis) + * with 'IRQF_NO_AUTOEN' anyways. + */ + if (!adis->data->unmasked_drdy) +- adis_enable_irq(adis, false); ++ __adis_enable_irq(adis, false); + + if (!adis->data->prod_id_reg) + return 0; +diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c +index 3d78da2531a9a..727e2ef66aa4b 100644 +--- a/drivers/iio/industrialio-event.c ++++ b/drivers/iio/industrialio-event.c +@@ -556,7 +556,7 @@ int iio_device_register_eventset(struct iio_dev *indio_dev) + + ret = iio_device_register_sysfs_group(indio_dev, &ev_int->group); + if (ret) +- goto error_free_setup_event_lines; ++ goto error_free_group_attrs; + + ev_int->ioctl_handler.ioctl = iio_event_ioctl; + iio_device_ioctl_handler_register(&iio_dev_opaque->indio_dev, +@@ -564,6 +564,8 @@ int iio_device_register_eventset(struct iio_dev *indio_dev) + + return 0; + ++error_free_group_attrs: ++ kfree(ev_int->group.attrs); + error_free_setup_event_lines: + iio_free_chan_devattr_list(&ev_int->dev_attr_list); + kfree(ev_int); +diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c +index a60ccf1836872..1117991ca2ab6 100644 +--- a/drivers/iio/temperature/ltc2983.c ++++ b/drivers/iio/temperature/ltc2983.c +@@ -209,6 +209,7 @@ struct ltc2983_data { + * Holds the converted temperature + */ + __be32 temp __aligned(IIO_DMA_MINALIGN); ++ __be32 chan_val; + }; + + struct ltc2983_sensor { +@@ -313,19 +314,18 @@ static int __ltc2983_fault_handler(const struct ltc2983_data *st, + return 0; + } + +-static int __ltc2983_chan_assign_common(const struct ltc2983_data *st, ++static int __ltc2983_chan_assign_common(struct ltc2983_data *st, + const struct ltc2983_sensor *sensor, + u32 chan_val) + { + u32 reg = LTC2983_CHAN_START_ADDR(sensor->chan); +- __be32 __chan_val; + + chan_val |= LTC2983_CHAN_TYPE(sensor->type); + dev_dbg(&st->spi->dev, "Assign reg:0x%04X, val:0x%08X\n", reg, + chan_val); +- __chan_val = cpu_to_be32(chan_val); +- return regmap_bulk_write(st->regmap, reg, &__chan_val, +- sizeof(__chan_val)); ++ st->chan_val = cpu_to_be32(chan_val); ++ return regmap_bulk_write(st->regmap, reg, &st->chan_val, ++ sizeof(st->chan_val)); + } + + static int __ltc2983_chan_custom_sensor_assign(struct ltc2983_data *st, +diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig +index aa36ac618e729..17a2274152771 100644 +--- a/drivers/infiniband/Kconfig ++++ b/drivers/infiniband/Kconfig +@@ -78,6 +78,7 @@ config INFINIBAND_VIRT_DMA + def_bool !HIGHMEM + + if INFINIBAND_USER_ACCESS || !INFINIBAND_USER_ACCESS ++if !UML + source "drivers/infiniband/hw/bnxt_re/Kconfig" + source "drivers/infiniband/hw/cxgb4/Kconfig" + source "drivers/infiniband/hw/efa/Kconfig" +@@ -94,6 +95,7 @@ source "drivers/infiniband/hw/qib/Kconfig" + source "drivers/infiniband/hw/usnic/Kconfig" + source "drivers/infiniband/hw/vmw_pvrdma/Kconfig" + source "drivers/infiniband/sw/rdmavt/Kconfig" ++endif # !UML + source "drivers/infiniband/sw/rxe/Kconfig" + source "drivers/infiniband/sw/siw/Kconfig" + endif +diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c +index b69e2c4e4d2a4..3c422698a51c1 100644 +--- a/drivers/infiniband/core/device.c ++++ b/drivers/infiniband/core/device.c +@@ -2851,8 +2851,8 @@ err: + static void __exit ib_core_cleanup(void) + { + roce_gid_mgmt_cleanup(); +- nldev_exit(); + rdma_nl_unregister(RDMA_NL_LS); ++ nldev_exit(); + unregister_pernet_device(&rdma_dev_net_ops); + unregister_blocking_lsm_notifier(&ibdev_lsm_nb); + ib_sa_cleanup(); +diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c +index 1893aa613ad73..674344eb8e2f4 100644 +--- a/drivers/infiniband/core/mad.c ++++ b/drivers/infiniband/core/mad.c +@@ -59,9 +59,6 @@ static void create_mad_addr_info(struct ib_mad_send_wr_private *mad_send_wr, + struct ib_mad_qp_info *qp_info, + struct trace_event_raw_ib_mad_send_template *entry) + { +- u16 pkey; +- struct ib_device *dev = qp_info->port_priv->device; +- u32 pnum = qp_info->port_priv->port_num; + struct ib_ud_wr *wr = &mad_send_wr->send_wr; + struct rdma_ah_attr attr = {}; + +@@ -69,8 +66,6 @@ static void create_mad_addr_info(struct ib_mad_send_wr_private *mad_send_wr, + + /* These are common */ + entry->sl = attr.sl; +- ib_query_pkey(dev, pnum, wr->pkey_index, &pkey); +- entry->pkey = pkey; + entry->rqpn = wr->remote_qpn; + entry->rqkey = wr->remote_qkey; + entry->dlid = rdma_ah_get_dlid(&attr); +diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c +index 12dc97067ed2b..222733a83ddb7 100644 +--- a/drivers/infiniband/core/nldev.c ++++ b/drivers/infiniband/core/nldev.c +@@ -513,7 +513,7 @@ static int fill_res_qp_entry(struct sk_buff *msg, bool has_cap_net_admin, + + /* In create_qp() port is not set yet */ + if (qp->port && nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, qp->port)) +- return -EINVAL; ++ return -EMSGSIZE; + + ret = nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, qp->qp_num); + if (ret) +@@ -552,7 +552,7 @@ static int fill_res_cm_id_entry(struct sk_buff *msg, bool has_cap_net_admin, + struct rdma_cm_id *cm_id = &id_priv->id; + + if (port && port != cm_id->port_num) +- return 0; ++ return -EAGAIN; + + if (cm_id->port_num && + nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, cm_id->port_num)) +@@ -894,6 +894,8 @@ static int fill_stat_counter_qps(struct sk_buff *msg, + int ret = 0; + + table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_QP); ++ if (!table_attr) ++ return -EMSGSIZE; + + rt = &counter->device->res[RDMA_RESTRACK_QP]; + xa_lock(&rt->xa); +diff --git a/drivers/infiniband/core/restrack.c b/drivers/infiniband/core/restrack.c +index 1f935d9f61785..01a499a8b88db 100644 +--- a/drivers/infiniband/core/restrack.c ++++ b/drivers/infiniband/core/restrack.c +@@ -343,8 +343,6 @@ void rdma_restrack_del(struct rdma_restrack_entry *res) + rt = &dev->res[res->type]; + + old = xa_erase(&rt->xa, res->id); +- if (res->type == RDMA_RESTRACK_MR) +- return; + WARN_ON(old != res); + + out: +diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c +index 84c53bd2a52db..ee59d73915689 100644 +--- a/drivers/infiniband/core/sysfs.c ++++ b/drivers/infiniband/core/sysfs.c +@@ -1213,6 +1213,9 @@ static struct ib_port *setup_port(struct ib_core_device *coredev, int port_num, + p->port_num = port_num; + kobject_init(&p->kobj, &port_type); + ++ if (device->port_data && is_full_dev) ++ device->port_data[port_num].sysfs = p; ++ + cur_group = p->groups_list; + ret = alloc_port_table_group("gids", &p->groups[0], p->attrs_list, + attr->gid_tbl_len, show_port_gid); +@@ -1258,9 +1261,6 @@ static struct ib_port *setup_port(struct ib_core_device *coredev, int port_num, + } + + list_add_tail(&p->kobj.entry, &coredev->port_list); +- if (device->port_data && is_full_dev) +- device->port_data[port_num].sysfs = p; +- + return p; + + err_groups: +@@ -1268,6 +1268,8 @@ err_groups: + err_del: + kobject_del(&p->kobj); + err_put: ++ if (device->port_data && is_full_dev) ++ device->port_data[port_num].sysfs = NULL; + kobject_put(&p->kobj); + return ERR_PTR(ret); + } +@@ -1276,14 +1278,17 @@ static void destroy_port(struct ib_core_device *coredev, struct ib_port *port) + { + bool is_full_dev = &port->ibdev->coredev == coredev; + +- if (port->ibdev->port_data && +- port->ibdev->port_data[port->port_num].sysfs == port) +- port->ibdev->port_data[port->port_num].sysfs = NULL; + list_del(&port->kobj.entry); + if (is_full_dev) + sysfs_remove_groups(&port->kobj, port->ibdev->ops.port_groups); ++ + sysfs_remove_groups(&port->kobj, port->groups_list); + kobject_del(&port->kobj); ++ ++ if (port->ibdev->port_data && ++ port->ibdev->port_data[port->port_num].sysfs == port) ++ port->ibdev->port_data[port->port_num].sysfs = NULL; ++ + kobject_put(&port->kobj); + } + +diff --git a/drivers/infiniband/hw/hfi1/affinity.c b/drivers/infiniband/hw/hfi1/affinity.c +index 877f8e84a672a..77ee77d4000fb 100644 +--- a/drivers/infiniband/hw/hfi1/affinity.c ++++ b/drivers/infiniband/hw/hfi1/affinity.c +@@ -177,6 +177,8 @@ out: + for (node = 0; node < node_affinity.num_possible_nodes; node++) + hfi1_per_node_cntr[node] = 1; + ++ pci_dev_put(dev); ++ + return 0; + } + +diff --git a/drivers/infiniband/hw/hfi1/firmware.c b/drivers/infiniband/hw/hfi1/firmware.c +index 1d77514ebbee0..0c0cef5b1e0e5 100644 +--- a/drivers/infiniband/hw/hfi1/firmware.c ++++ b/drivers/infiniband/hw/hfi1/firmware.c +@@ -1743,6 +1743,7 @@ int parse_platform_config(struct hfi1_devdata *dd) + + if (!dd->platform_config.data) { + dd_dev_err(dd, "%s: Missing config file\n", __func__); ++ ret = -EINVAL; + goto bail; + } + ptr = (u32 *)dd->platform_config.data; +@@ -1751,6 +1752,7 @@ int parse_platform_config(struct hfi1_devdata *dd) + ptr++; + if (magic_num != PLATFORM_CONFIG_MAGIC_NUM) { + dd_dev_err(dd, "%s: Bad config file\n", __func__); ++ ret = -EINVAL; + goto bail; + } + +@@ -1774,6 +1776,7 @@ int parse_platform_config(struct hfi1_devdata *dd) + if (file_length > dd->platform_config.size) { + dd_dev_info(dd, "%s:File claims to be larger than read size\n", + __func__); ++ ret = -EINVAL; + goto bail; + } else if (file_length < dd->platform_config.size) { + dd_dev_info(dd, +@@ -1794,6 +1797,7 @@ int parse_platform_config(struct hfi1_devdata *dd) + dd_dev_err(dd, "%s: Failed validation at offset %ld\n", + __func__, (ptr - (u32 *) + dd->platform_config.data)); ++ ret = -EINVAL; + goto bail; + } + +@@ -1837,6 +1841,7 @@ int parse_platform_config(struct hfi1_devdata *dd) + __func__, table_type, + (ptr - (u32 *) + dd->platform_config.data)); ++ ret = -EINVAL; + goto bail; /* We don't trust this file now */ + } + pcfgcache->config_tables[table_type].table = ptr; +@@ -1856,6 +1861,7 @@ int parse_platform_config(struct hfi1_devdata *dd) + __func__, table_type, + (ptr - + (u32 *)dd->platform_config.data)); ++ ret = -EINVAL; + goto bail; /* We don't trust this file now */ + } + pcfgcache->config_tables[table_type].table_metadata = +diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h +index 723e55a7de8d9..f701cc86896b3 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_device.h ++++ b/drivers/infiniband/hw/hns/hns_roce_device.h +@@ -202,6 +202,7 @@ struct hns_roce_ucontext { + struct list_head page_list; + struct mutex page_mutex; + struct hns_user_mmap_entry *db_mmap_entry; ++ u32 config; + }; + + struct hns_roce_pd { +@@ -334,6 +335,7 @@ struct hns_roce_wq { + u32 head; + u32 tail; + void __iomem *db_reg; ++ u32 ext_sge_cnt; + }; + + struct hns_roce_sge { +@@ -635,6 +637,7 @@ struct hns_roce_qp { + struct list_head rq_node; /* all recv qps are on a list */ + struct list_head sq_node; /* all send qps are on a list */ + struct hns_user_mmap_entry *dwqe_mmap_entry; ++ u32 config; + }; + + struct hns_roce_ib_iboe { +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index 1435fe2ea176f..b2421883993b1 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -192,7 +192,6 @@ static int fill_ext_sge_inl_data(struct hns_roce_qp *qp, + unsigned int *sge_idx, u32 msg_len) + { + struct ib_device *ibdev = &(to_hr_dev(qp->ibqp.device))->ib_dev; +- unsigned int ext_sge_sz = qp->sq.max_gs * HNS_ROCE_SGE_SIZE; + unsigned int left_len_in_pg; + unsigned int idx = *sge_idx; + unsigned int i = 0; +@@ -200,7 +199,7 @@ static int fill_ext_sge_inl_data(struct hns_roce_qp *qp, + void *addr; + void *dseg; + +- if (msg_len > ext_sge_sz) { ++ if (msg_len > qp->sq.ext_sge_cnt * HNS_ROCE_SGE_SIZE) { + ibdev_err(ibdev, + "no enough extended sge space for inline data.\n"); + return -EINVAL; +@@ -1274,6 +1273,30 @@ static void update_cmdq_status(struct hns_roce_dev *hr_dev) + hr_dev->cmd.state = HNS_ROCE_CMDQ_STATE_FATAL_ERR; + } + ++static int hns_roce_cmd_err_convert_errno(u16 desc_ret) ++{ ++ struct hns_roce_cmd_errcode errcode_table[] = { ++ {CMD_EXEC_SUCCESS, 0}, ++ {CMD_NO_AUTH, -EPERM}, ++ {CMD_NOT_EXIST, -EOPNOTSUPP}, ++ {CMD_CRQ_FULL, -EXFULL}, ++ {CMD_NEXT_ERR, -ENOSR}, ++ {CMD_NOT_EXEC, -ENOTBLK}, ++ {CMD_PARA_ERR, -EINVAL}, ++ {CMD_RESULT_ERR, -ERANGE}, ++ {CMD_TIMEOUT, -ETIME}, ++ {CMD_HILINK_ERR, -ENOLINK}, ++ {CMD_INFO_ILLEGAL, -ENXIO}, ++ {CMD_INVALID, -EBADR}, ++ }; ++ u16 i; ++ ++ for (i = 0; i < ARRAY_SIZE(errcode_table); i++) ++ if (desc_ret == errcode_table[i].return_status) ++ return errcode_table[i].errno; ++ return -EIO; ++} ++ + static int __hns_roce_cmq_send(struct hns_roce_dev *hr_dev, + struct hns_roce_cmq_desc *desc, int num) + { +@@ -1319,7 +1342,7 @@ static int __hns_roce_cmq_send(struct hns_roce_dev *hr_dev, + dev_err_ratelimited(hr_dev->dev, + "Cmdq IO error, opcode = 0x%x, return = 0x%x.\n", + desc->opcode, desc_ret); +- ret = -EIO; ++ ret = hns_roce_cmd_err_convert_errno(desc_ret); + } + } else { + /* FW/HW reset or incorrect number of desc */ +@@ -2024,13 +2047,14 @@ static void set_default_caps(struct hns_roce_dev *hr_dev) + + caps->flags |= HNS_ROCE_CAP_FLAG_ATOMIC | HNS_ROCE_CAP_FLAG_MW | + HNS_ROCE_CAP_FLAG_SRQ | HNS_ROCE_CAP_FLAG_FRMR | +- HNS_ROCE_CAP_FLAG_QP_FLOW_CTRL | HNS_ROCE_CAP_FLAG_XRC; ++ HNS_ROCE_CAP_FLAG_QP_FLOW_CTRL; + + caps->gid_table_len[0] = HNS_ROCE_V2_GID_INDEX_NUM; + + if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP09) { + caps->flags |= HNS_ROCE_CAP_FLAG_STASH | +- HNS_ROCE_CAP_FLAG_DIRECT_WQE; ++ HNS_ROCE_CAP_FLAG_DIRECT_WQE | ++ HNS_ROCE_CAP_FLAG_XRC; + caps->max_sq_inline = HNS_ROCE_V3_MAX_SQ_INLINE; + } else { + caps->max_sq_inline = HNS_ROCE_V2_MAX_SQ_INLINE; +@@ -2342,6 +2366,9 @@ static int hns_roce_query_pf_caps(struct hns_roce_dev *hr_dev) + caps->wqe_sge_hop_num = hr_reg_read(resp_d, PF_CAPS_D_EX_SGE_HOP_NUM); + caps->wqe_rq_hop_num = hr_reg_read(resp_d, PF_CAPS_D_RQWQE_HOP_NUM); + ++ if (!(caps->page_size_cap & PAGE_SIZE)) ++ caps->page_size_cap = HNS_ROCE_V2_PAGE_SIZE_SUPPORTED; ++ + return 0; + } + +@@ -2631,31 +2658,124 @@ static void free_dip_list(struct hns_roce_dev *hr_dev) + spin_unlock_irqrestore(&hr_dev->dip_list_lock, flags); + } + +-static void free_mr_exit(struct hns_roce_dev *hr_dev) ++static struct ib_pd *free_mr_init_pd(struct hns_roce_dev *hr_dev) ++{ ++ struct hns_roce_v2_priv *priv = hr_dev->priv; ++ struct hns_roce_v2_free_mr *free_mr = &priv->free_mr; ++ struct ib_device *ibdev = &hr_dev->ib_dev; ++ struct hns_roce_pd *hr_pd; ++ struct ib_pd *pd; ++ ++ hr_pd = kzalloc(sizeof(*hr_pd), GFP_KERNEL); ++ if (ZERO_OR_NULL_PTR(hr_pd)) ++ return NULL; ++ pd = &hr_pd->ibpd; ++ pd->device = ibdev; ++ ++ if (hns_roce_alloc_pd(pd, NULL)) { ++ ibdev_err(ibdev, "failed to create pd for free mr.\n"); ++ kfree(hr_pd); ++ return NULL; ++ } ++ free_mr->rsv_pd = to_hr_pd(pd); ++ free_mr->rsv_pd->ibpd.device = &hr_dev->ib_dev; ++ free_mr->rsv_pd->ibpd.uobject = NULL; ++ free_mr->rsv_pd->ibpd.__internal_mr = NULL; ++ atomic_set(&free_mr->rsv_pd->ibpd.usecnt, 0); ++ ++ return pd; ++} ++ ++static struct ib_cq *free_mr_init_cq(struct hns_roce_dev *hr_dev) + { + struct hns_roce_v2_priv *priv = hr_dev->priv; + struct hns_roce_v2_free_mr *free_mr = &priv->free_mr; ++ struct ib_device *ibdev = &hr_dev->ib_dev; ++ struct ib_cq_init_attr cq_init_attr = {}; ++ struct hns_roce_cq *hr_cq; ++ struct ib_cq *cq; ++ ++ cq_init_attr.cqe = HNS_ROCE_FREE_MR_USED_CQE_NUM; ++ ++ hr_cq = kzalloc(sizeof(*hr_cq), GFP_KERNEL); ++ if (ZERO_OR_NULL_PTR(hr_cq)) ++ return NULL; ++ ++ cq = &hr_cq->ib_cq; ++ cq->device = ibdev; ++ ++ if (hns_roce_create_cq(cq, &cq_init_attr, NULL)) { ++ ibdev_err(ibdev, "failed to create cq for free mr.\n"); ++ kfree(hr_cq); ++ return NULL; ++ } ++ free_mr->rsv_cq = to_hr_cq(cq); ++ free_mr->rsv_cq->ib_cq.device = &hr_dev->ib_dev; ++ free_mr->rsv_cq->ib_cq.uobject = NULL; ++ free_mr->rsv_cq->ib_cq.comp_handler = NULL; ++ free_mr->rsv_cq->ib_cq.event_handler = NULL; ++ free_mr->rsv_cq->ib_cq.cq_context = NULL; ++ atomic_set(&free_mr->rsv_cq->ib_cq.usecnt, 0); ++ ++ return cq; ++} ++ ++static int free_mr_init_qp(struct hns_roce_dev *hr_dev, struct ib_cq *cq, ++ struct ib_qp_init_attr *init_attr, int i) ++{ ++ struct hns_roce_v2_priv *priv = hr_dev->priv; ++ struct hns_roce_v2_free_mr *free_mr = &priv->free_mr; ++ struct ib_device *ibdev = &hr_dev->ib_dev; ++ struct hns_roce_qp *hr_qp; ++ struct ib_qp *qp; + int ret; ++ ++ hr_qp = kzalloc(sizeof(*hr_qp), GFP_KERNEL); ++ if (ZERO_OR_NULL_PTR(hr_qp)) ++ return -ENOMEM; ++ ++ qp = &hr_qp->ibqp; ++ qp->device = ibdev; ++ ++ ret = hns_roce_create_qp(qp, init_attr, NULL); ++ if (ret) { ++ ibdev_err(ibdev, "failed to create qp for free mr.\n"); ++ kfree(hr_qp); ++ return ret; ++ } ++ ++ free_mr->rsv_qp[i] = hr_qp; ++ free_mr->rsv_qp[i]->ibqp.recv_cq = cq; ++ free_mr->rsv_qp[i]->ibqp.send_cq = cq; ++ ++ return 0; ++} ++ ++static void free_mr_exit(struct hns_roce_dev *hr_dev) ++{ ++ struct hns_roce_v2_priv *priv = hr_dev->priv; ++ struct hns_roce_v2_free_mr *free_mr = &priv->free_mr; ++ struct ib_qp *qp; + int i; + + for (i = 0; i < ARRAY_SIZE(free_mr->rsv_qp); i++) { + if (free_mr->rsv_qp[i]) { +- ret = ib_destroy_qp(free_mr->rsv_qp[i]); +- if (ret) +- ibdev_err(&hr_dev->ib_dev, +- "failed to destroy qp in free mr.\n"); +- ++ qp = &free_mr->rsv_qp[i]->ibqp; ++ hns_roce_v2_destroy_qp(qp, NULL); ++ kfree(free_mr->rsv_qp[i]); + free_mr->rsv_qp[i] = NULL; + } + } + + if (free_mr->rsv_cq) { +- ib_destroy_cq(free_mr->rsv_cq); ++ hns_roce_destroy_cq(&free_mr->rsv_cq->ib_cq, NULL); ++ kfree(free_mr->rsv_cq); + free_mr->rsv_cq = NULL; + } + + if (free_mr->rsv_pd) { +- ib_dealloc_pd(free_mr->rsv_pd); ++ hns_roce_dealloc_pd(&free_mr->rsv_pd->ibpd, NULL); ++ kfree(free_mr->rsv_pd); + free_mr->rsv_pd = NULL; + } + } +@@ -2664,55 +2784,46 @@ static int free_mr_alloc_res(struct hns_roce_dev *hr_dev) + { + struct hns_roce_v2_priv *priv = hr_dev->priv; + struct hns_roce_v2_free_mr *free_mr = &priv->free_mr; +- struct ib_device *ibdev = &hr_dev->ib_dev; +- struct ib_cq_init_attr cq_init_attr = {}; + struct ib_qp_init_attr qp_init_attr = {}; + struct ib_pd *pd; + struct ib_cq *cq; +- struct ib_qp *qp; + int ret; + int i; + +- pd = ib_alloc_pd(ibdev, 0); +- if (IS_ERR(pd)) { +- ibdev_err(ibdev, "failed to create pd for free mr.\n"); +- return PTR_ERR(pd); +- } +- free_mr->rsv_pd = pd; ++ pd = free_mr_init_pd(hr_dev); ++ if (!pd) ++ return -ENOMEM; + +- cq_init_attr.cqe = HNS_ROCE_FREE_MR_USED_CQE_NUM; +- cq = ib_create_cq(ibdev, NULL, NULL, NULL, &cq_init_attr); +- if (IS_ERR(cq)) { +- ibdev_err(ibdev, "failed to create cq for free mr.\n"); +- ret = PTR_ERR(cq); +- goto create_failed; ++ cq = free_mr_init_cq(hr_dev); ++ if (!cq) { ++ ret = -ENOMEM; ++ goto create_failed_cq; + } +- free_mr->rsv_cq = cq; + + qp_init_attr.qp_type = IB_QPT_RC; + qp_init_attr.sq_sig_type = IB_SIGNAL_ALL_WR; +- qp_init_attr.send_cq = free_mr->rsv_cq; +- qp_init_attr.recv_cq = free_mr->rsv_cq; ++ qp_init_attr.send_cq = cq; ++ qp_init_attr.recv_cq = cq; + for (i = 0; i < ARRAY_SIZE(free_mr->rsv_qp); i++) { + qp_init_attr.cap.max_send_wr = HNS_ROCE_FREE_MR_USED_SQWQE_NUM; + qp_init_attr.cap.max_send_sge = HNS_ROCE_FREE_MR_USED_SQSGE_NUM; + qp_init_attr.cap.max_recv_wr = HNS_ROCE_FREE_MR_USED_RQWQE_NUM; + qp_init_attr.cap.max_recv_sge = HNS_ROCE_FREE_MR_USED_RQSGE_NUM; + +- qp = ib_create_qp(free_mr->rsv_pd, &qp_init_attr); +- if (IS_ERR(qp)) { +- ibdev_err(ibdev, "failed to create qp for free mr.\n"); +- ret = PTR_ERR(qp); +- goto create_failed; +- } +- +- free_mr->rsv_qp[i] = qp; ++ ret = free_mr_init_qp(hr_dev, cq, &qp_init_attr, i); ++ if (ret) ++ goto create_failed_qp; + } + + return 0; + +-create_failed: +- free_mr_exit(hr_dev); ++create_failed_qp: ++ hns_roce_destroy_cq(cq, NULL); ++ kfree(cq); ++ ++create_failed_cq: ++ hns_roce_dealloc_pd(pd, NULL); ++ kfree(pd); + + return ret; + } +@@ -2728,14 +2839,17 @@ static int free_mr_modify_rsv_qp(struct hns_roce_dev *hr_dev, + int mask; + int ret; + +- hr_qp = to_hr_qp(free_mr->rsv_qp[sl_num]); ++ hr_qp = to_hr_qp(&free_mr->rsv_qp[sl_num]->ibqp); + hr_qp->free_mr_en = 1; ++ hr_qp->ibqp.device = ibdev; ++ hr_qp->ibqp.qp_type = IB_QPT_RC; + + mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT | IB_QP_ACCESS_FLAGS; + attr->qp_state = IB_QPS_INIT; + attr->port_num = 1; + attr->qp_access_flags = IB_ACCESS_REMOTE_WRITE; +- ret = ib_modify_qp(&hr_qp->ibqp, attr, mask); ++ ret = hr_dev->hw->modify_qp(&hr_qp->ibqp, attr, mask, IB_QPS_INIT, ++ IB_QPS_INIT); + if (ret) { + ibdev_err(ibdev, "failed to modify qp to init, ret = %d.\n", + ret); +@@ -2756,7 +2870,8 @@ static int free_mr_modify_rsv_qp(struct hns_roce_dev *hr_dev, + + rdma_ah_set_sl(&attr->ah_attr, (u8)sl_num); + +- ret = ib_modify_qp(&hr_qp->ibqp, attr, mask); ++ ret = hr_dev->hw->modify_qp(&hr_qp->ibqp, attr, mask, IB_QPS_INIT, ++ IB_QPS_RTR); + hr_dev->loop_idc = loopback; + if (ret) { + ibdev_err(ibdev, "failed to modify qp to rtr, ret = %d.\n", +@@ -2770,7 +2885,8 @@ static int free_mr_modify_rsv_qp(struct hns_roce_dev *hr_dev, + attr->sq_psn = HNS_ROCE_FREE_MR_USED_PSN; + attr->retry_cnt = HNS_ROCE_FREE_MR_USED_QP_RETRY_CNT; + attr->timeout = HNS_ROCE_FREE_MR_USED_QP_TIMEOUT; +- ret = ib_modify_qp(&hr_qp->ibqp, attr, mask); ++ ret = hr_dev->hw->modify_qp(&hr_qp->ibqp, attr, mask, IB_QPS_RTR, ++ IB_QPS_RTS); + if (ret) + ibdev_err(ibdev, "failed to modify qp to rts, ret = %d.\n", + ret); +@@ -3186,7 +3302,8 @@ static int set_mtpt_pbl(struct hns_roce_dev *hr_dev, + int i, count; + + count = hns_roce_mtr_find(hr_dev, &mr->pbl_mtr, 0, pages, +- ARRAY_SIZE(pages), &pbl_ba); ++ min_t(int, ARRAY_SIZE(pages), mr->npages), ++ &pbl_ba); + if (count < 1) { + ibdev_err(ibdev, "failed to find PBL mtr, count = %d.\n", + count); +@@ -3414,7 +3531,7 @@ static void free_mr_send_cmd_to_hw(struct hns_roce_dev *hr_dev) + mutex_lock(&free_mr->mutex); + + for (i = 0; i < ARRAY_SIZE(free_mr->rsv_qp); i++) { +- hr_qp = to_hr_qp(free_mr->rsv_qp[i]); ++ hr_qp = free_mr->rsv_qp[i]; + + ret = free_mr_post_send_lp_wqe(hr_qp); + if (ret) { +@@ -3429,7 +3546,7 @@ static void free_mr_send_cmd_to_hw(struct hns_roce_dev *hr_dev) + + end = msecs_to_jiffies(HNS_ROCE_V2_FREE_MR_TIMEOUT) + jiffies; + while (cqe_cnt) { +- npolled = hns_roce_v2_poll_cq(free_mr->rsv_cq, cqe_cnt, wc); ++ npolled = hns_roce_v2_poll_cq(&free_mr->rsv_cq->ib_cq, cqe_cnt, wc); + if (npolled < 0) { + ibdev_err(ibdev, + "failed to poll cqe for free mr, remain %d cqe.\n", +@@ -5375,6 +5492,8 @@ static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, + + rdma_ah_set_sl(&qp_attr->ah_attr, + hr_reg_read(&context, QPC_SL)); ++ rdma_ah_set_port_num(&qp_attr->ah_attr, hr_qp->port + 1); ++ rdma_ah_set_ah_flags(&qp_attr->ah_attr, IB_AH_GRH); + grh->flow_label = hr_reg_read(&context, QPC_FL); + grh->sgid_index = hr_reg_read(&context, QPC_GMV_IDX); + grh->hop_limit = hr_reg_read(&context, QPC_HOPLIMIT); +@@ -5468,7 +5587,7 @@ static int hns_roce_v2_destroy_qp_common(struct hns_roce_dev *hr_dev, + return ret; + } + +-static int hns_roce_v2_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata) ++int hns_roce_v2_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata) + { + struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device); + struct hns_roce_qp *hr_qp = to_hr_qp(ibqp); +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +index c7bf2d52c1cdb..b1b3e1e0b84e5 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +@@ -272,6 +272,11 @@ enum hns_roce_cmd_return_status { + CMD_OTHER_ERR = 0xff + }; + ++struct hns_roce_cmd_errcode { ++ enum hns_roce_cmd_return_status return_status; ++ int errno; ++}; ++ + enum hns_roce_sgid_type { + GID_TYPE_FLAG_ROCE_V1 = 0, + GID_TYPE_FLAG_ROCE_V2_IPV4, +@@ -1327,9 +1332,9 @@ struct hns_roce_link_table { + #define HNS_ROCE_EXT_LLM_MIN_PAGES(que_num) ((que_num) * 4 + 2) + + struct hns_roce_v2_free_mr { +- struct ib_qp *rsv_qp[HNS_ROCE_FREE_MR_USED_QP_NUM]; +- struct ib_cq *rsv_cq; +- struct ib_pd *rsv_pd; ++ struct hns_roce_qp *rsv_qp[HNS_ROCE_FREE_MR_USED_QP_NUM]; ++ struct hns_roce_cq *rsv_cq; ++ struct hns_roce_pd *rsv_pd; + struct mutex mutex; + }; + +@@ -1459,6 +1464,8 @@ struct hns_roce_sccc_clr_done { + __le32 rsv[5]; + }; + ++int hns_roce_v2_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata); ++ + static inline void hns_roce_write64(struct hns_roce_dev *hr_dev, __le32 val[2], + void __iomem *dest) + { +diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c +index dcf89689a4c62..8ba68ac12388d 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_main.c ++++ b/drivers/infiniband/hw/hns/hns_roce_main.c +@@ -354,10 +354,11 @@ static int hns_roce_alloc_uar_entry(struct ib_ucontext *uctx) + static int hns_roce_alloc_ucontext(struct ib_ucontext *uctx, + struct ib_udata *udata) + { +- int ret; + struct hns_roce_ucontext *context = to_hr_ucontext(uctx); +- struct hns_roce_ib_alloc_ucontext_resp resp = {}; + struct hns_roce_dev *hr_dev = to_hr_dev(uctx->device); ++ struct hns_roce_ib_alloc_ucontext_resp resp = {}; ++ struct hns_roce_ib_alloc_ucontext ucmd = {}; ++ int ret; + + if (!hr_dev->active) + return -EAGAIN; +@@ -365,6 +366,19 @@ static int hns_roce_alloc_ucontext(struct ib_ucontext *uctx, + resp.qp_tab_size = hr_dev->caps.num_qps; + resp.srq_tab_size = hr_dev->caps.num_srqs; + ++ ret = ib_copy_from_udata(&ucmd, udata, ++ min(udata->inlen, sizeof(ucmd))); ++ if (ret) ++ return ret; ++ ++ if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP09) ++ context->config = ucmd.config & HNS_ROCE_EXSGE_FLAGS; ++ ++ if (context->config & HNS_ROCE_EXSGE_FLAGS) { ++ resp.config |= HNS_ROCE_RSP_EXSGE_FLAGS; ++ resp.max_inline_data = hr_dev->caps.max_sq_inline; ++ } ++ + ret = hns_roce_uar_alloc(hr_dev, &context->uar); + if (ret) + goto error_fail_uar_alloc; +diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c +index 845ac7d3831f4..37a5cf62f88b4 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_mr.c ++++ b/drivers/infiniband/hw/hns/hns_roce_mr.c +@@ -392,10 +392,10 @@ struct ib_mr *hns_roce_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, + + return &mr->ibmr; + +-err_key: +- free_mr_key(hr_dev, mr); + err_pbl: + free_mr_pbl(hr_dev, mr); ++err_key: ++ free_mr_key(hr_dev, mr); + err_free: + kfree(mr); + return ERR_PTR(ret); +diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c +index f0bd82a18069a..0ae335fb205ca 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_qp.c ++++ b/drivers/infiniband/hw/hns/hns_roce_qp.c +@@ -476,38 +476,109 @@ static int set_rq_size(struct hns_roce_dev *hr_dev, struct ib_qp_cap *cap, + return 0; + } + +-static u32 get_wqe_ext_sge_cnt(struct hns_roce_qp *qp) ++static u32 get_max_inline_data(struct hns_roce_dev *hr_dev, ++ struct ib_qp_cap *cap) + { +- /* GSI/UD QP only has extended sge */ +- if (qp->ibqp.qp_type == IB_QPT_GSI || qp->ibqp.qp_type == IB_QPT_UD) +- return qp->sq.max_gs; +- +- if (qp->sq.max_gs > HNS_ROCE_SGE_IN_WQE) +- return qp->sq.max_gs - HNS_ROCE_SGE_IN_WQE; ++ if (cap->max_inline_data) { ++ cap->max_inline_data = roundup_pow_of_two(cap->max_inline_data); ++ return min(cap->max_inline_data, ++ hr_dev->caps.max_sq_inline); ++ } + + return 0; + } + ++static void update_inline_data(struct hns_roce_qp *hr_qp, ++ struct ib_qp_cap *cap) ++{ ++ u32 sge_num = hr_qp->sq.ext_sge_cnt; ++ ++ if (hr_qp->config & HNS_ROCE_EXSGE_FLAGS) { ++ if (!(hr_qp->ibqp.qp_type == IB_QPT_GSI || ++ hr_qp->ibqp.qp_type == IB_QPT_UD)) ++ sge_num = max((u32)HNS_ROCE_SGE_IN_WQE, sge_num); ++ ++ cap->max_inline_data = max(cap->max_inline_data, ++ sge_num * HNS_ROCE_SGE_SIZE); ++ } ++ ++ hr_qp->max_inline_data = cap->max_inline_data; ++} ++ ++static u32 get_sge_num_from_max_send_sge(bool is_ud_or_gsi, ++ u32 max_send_sge) ++{ ++ unsigned int std_sge_num; ++ unsigned int min_sge; ++ ++ std_sge_num = is_ud_or_gsi ? 0 : HNS_ROCE_SGE_IN_WQE; ++ min_sge = is_ud_or_gsi ? 1 : 0; ++ return max_send_sge > std_sge_num ? (max_send_sge - std_sge_num) : ++ min_sge; ++} ++ ++static unsigned int get_sge_num_from_max_inl_data(bool is_ud_or_gsi, ++ u32 max_inline_data) ++{ ++ unsigned int inline_sge; ++ ++ inline_sge = roundup_pow_of_two(max_inline_data) / HNS_ROCE_SGE_SIZE; ++ ++ /* ++ * if max_inline_data less than ++ * HNS_ROCE_SGE_IN_WQE * HNS_ROCE_SGE_SIZE, ++ * In addition to ud's mode, no need to extend sge. ++ */ ++ if (!is_ud_or_gsi && inline_sge <= HNS_ROCE_SGE_IN_WQE) ++ inline_sge = 0; ++ ++ return inline_sge; ++} ++ + static void set_ext_sge_param(struct hns_roce_dev *hr_dev, u32 sq_wqe_cnt, + struct hns_roce_qp *hr_qp, struct ib_qp_cap *cap) + { ++ bool is_ud_or_gsi = (hr_qp->ibqp.qp_type == IB_QPT_GSI || ++ hr_qp->ibqp.qp_type == IB_QPT_UD); ++ unsigned int std_sge_num; ++ u32 inline_ext_sge = 0; ++ u32 ext_wqe_sge_cnt; + u32 total_sge_cnt; +- u32 wqe_sge_cnt; ++ ++ cap->max_inline_data = get_max_inline_data(hr_dev, cap); + + hr_qp->sge.sge_shift = HNS_ROCE_SGE_SHIFT; ++ std_sge_num = is_ud_or_gsi ? 0 : HNS_ROCE_SGE_IN_WQE; ++ ext_wqe_sge_cnt = get_sge_num_from_max_send_sge(is_ud_or_gsi, ++ cap->max_send_sge); + +- hr_qp->sq.max_gs = max(1U, cap->max_send_sge); ++ if (hr_qp->config & HNS_ROCE_EXSGE_FLAGS) { ++ inline_ext_sge = max(ext_wqe_sge_cnt, ++ get_sge_num_from_max_inl_data(is_ud_or_gsi, ++ cap->max_inline_data)); ++ hr_qp->sq.ext_sge_cnt = inline_ext_sge ? ++ roundup_pow_of_two(inline_ext_sge) : 0; + +- wqe_sge_cnt = get_wqe_ext_sge_cnt(hr_qp); ++ hr_qp->sq.max_gs = max(1U, (hr_qp->sq.ext_sge_cnt + std_sge_num)); ++ hr_qp->sq.max_gs = min(hr_qp->sq.max_gs, hr_dev->caps.max_sq_sg); ++ ++ ext_wqe_sge_cnt = hr_qp->sq.ext_sge_cnt; ++ } else { ++ hr_qp->sq.max_gs = max(1U, cap->max_send_sge); ++ hr_qp->sq.max_gs = min(hr_qp->sq.max_gs, hr_dev->caps.max_sq_sg); ++ hr_qp->sq.ext_sge_cnt = hr_qp->sq.max_gs; ++ } + + /* If the number of extended sge is not zero, they MUST use the + * space of HNS_HW_PAGE_SIZE at least. + */ +- if (wqe_sge_cnt) { +- total_sge_cnt = roundup_pow_of_two(sq_wqe_cnt * wqe_sge_cnt); ++ if (ext_wqe_sge_cnt) { ++ total_sge_cnt = roundup_pow_of_two(sq_wqe_cnt * ext_wqe_sge_cnt); + hr_qp->sge.sge_cnt = max(total_sge_cnt, + (u32)HNS_HW_PAGE_SIZE / HNS_ROCE_SGE_SIZE); + } ++ ++ update_inline_data(hr_qp, cap); + } + + static int check_sq_size_with_integrity(struct hns_roce_dev *hr_dev, +@@ -556,6 +627,7 @@ static int set_user_sq_size(struct hns_roce_dev *hr_dev, + + hr_qp->sq.wqe_shift = ucmd->log_sq_stride; + hr_qp->sq.wqe_cnt = cnt; ++ cap->max_send_sge = hr_qp->sq.max_gs; + + return 0; + } +@@ -986,13 +1058,9 @@ static int set_qp_param(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp, + struct hns_roce_ib_create_qp *ucmd) + { + struct ib_device *ibdev = &hr_dev->ib_dev; ++ struct hns_roce_ucontext *uctx; + int ret; + +- if (init_attr->cap.max_inline_data > hr_dev->caps.max_sq_inline) +- init_attr->cap.max_inline_data = hr_dev->caps.max_sq_inline; +- +- hr_qp->max_inline_data = init_attr->cap.max_inline_data; +- + if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) + hr_qp->sq_signal_bits = IB_SIGNAL_ALL_WR; + else +@@ -1015,12 +1083,17 @@ static int set_qp_param(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp, + return ret; + } + ++ uctx = rdma_udata_to_drv_context(udata, struct hns_roce_ucontext, ++ ibucontext); ++ hr_qp->config = uctx->config; + ret = set_user_sq_size(hr_dev, &init_attr->cap, hr_qp, ucmd); + if (ret) + ibdev_err(ibdev, + "failed to set user SQ size, ret = %d.\n", + ret); + } else { ++ if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP09) ++ hr_qp->config = HNS_ROCE_EXSGE_FLAGS; + ret = set_kernel_sq_size(hr_dev, &init_attr->cap, hr_qp); + if (ret) + ibdev_err(ibdev, +diff --git a/drivers/infiniband/hw/irdma/uk.c b/drivers/infiniband/hw/irdma/uk.c +index a6e5d350a94ce..16183e894da77 100644 +--- a/drivers/infiniband/hw/irdma/uk.c ++++ b/drivers/infiniband/hw/irdma/uk.c +@@ -566,21 +566,37 @@ static void irdma_set_mw_bind_wqe_gen_1(__le64 *wqe, + + /** + * irdma_copy_inline_data_gen_1 - Copy inline data to wqe +- * @dest: pointer to wqe +- * @src: pointer to inline data +- * @len: length of inline data to copy ++ * @wqe: pointer to wqe ++ * @sge_list: table of pointers to inline data ++ * @num_sges: Total inline data length + * @polarity: compatibility parameter + */ +-static void irdma_copy_inline_data_gen_1(u8 *dest, u8 *src, u32 len, +- u8 polarity) ++static void irdma_copy_inline_data_gen_1(u8 *wqe, struct ib_sge *sge_list, ++ u32 num_sges, u8 polarity) + { +- if (len <= 16) { +- memcpy(dest, src, len); +- } else { +- memcpy(dest, src, 16); +- src += 16; +- dest = dest + 32; +- memcpy(dest, src, len - 16); ++ u32 quanta_bytes_remaining = 16; ++ int i; ++ ++ for (i = 0; i < num_sges; i++) { ++ u8 *cur_sge = (u8 *)(uintptr_t)sge_list[i].addr; ++ u32 sge_len = sge_list[i].length; ++ ++ while (sge_len) { ++ u32 bytes_copied; ++ ++ bytes_copied = min(sge_len, quanta_bytes_remaining); ++ memcpy(wqe, cur_sge, bytes_copied); ++ wqe += bytes_copied; ++ cur_sge += bytes_copied; ++ quanta_bytes_remaining -= bytes_copied; ++ sge_len -= bytes_copied; ++ ++ if (!quanta_bytes_remaining) { ++ /* Remaining inline bytes reside after hdr */ ++ wqe += 16; ++ quanta_bytes_remaining = 32; ++ } ++ } + } + } + +@@ -612,35 +628,51 @@ static void irdma_set_mw_bind_wqe(__le64 *wqe, + + /** + * irdma_copy_inline_data - Copy inline data to wqe +- * @dest: pointer to wqe +- * @src: pointer to inline data +- * @len: length of inline data to copy ++ * @wqe: pointer to wqe ++ * @sge_list: table of pointers to inline data ++ * @num_sges: number of SGE's + * @polarity: polarity of wqe valid bit + */ +-static void irdma_copy_inline_data(u8 *dest, u8 *src, u32 len, u8 polarity) ++static void irdma_copy_inline_data(u8 *wqe, struct ib_sge *sge_list, ++ u32 num_sges, u8 polarity) + { + u8 inline_valid = polarity << IRDMA_INLINE_VALID_S; +- u32 copy_size; +- +- dest += 8; +- if (len <= 8) { +- memcpy(dest, src, len); +- return; +- } +- +- *((u64 *)dest) = *((u64 *)src); +- len -= 8; +- src += 8; +- dest += 24; /* point to additional 32 byte quanta */ +- +- while (len) { +- copy_size = len < 31 ? len : 31; +- memcpy(dest, src, copy_size); +- *(dest + 31) = inline_valid; +- len -= copy_size; +- dest += 32; +- src += copy_size; ++ u32 quanta_bytes_remaining = 8; ++ bool first_quanta = true; ++ int i; ++ ++ wqe += 8; ++ ++ for (i = 0; i < num_sges; i++) { ++ u8 *cur_sge = (u8 *)(uintptr_t)sge_list[i].addr; ++ u32 sge_len = sge_list[i].length; ++ ++ while (sge_len) { ++ u32 bytes_copied; ++ ++ bytes_copied = min(sge_len, quanta_bytes_remaining); ++ memcpy(wqe, cur_sge, bytes_copied); ++ wqe += bytes_copied; ++ cur_sge += bytes_copied; ++ quanta_bytes_remaining -= bytes_copied; ++ sge_len -= bytes_copied; ++ ++ if (!quanta_bytes_remaining) { ++ quanta_bytes_remaining = 31; ++ ++ /* Remaining inline bytes reside after hdr */ ++ if (first_quanta) { ++ first_quanta = false; ++ wqe += 16; ++ } else { ++ *wqe = inline_valid; ++ wqe++; ++ } ++ } ++ } + } ++ if (!first_quanta && quanta_bytes_remaining < 31) ++ *(wqe + quanta_bytes_remaining) = inline_valid; + } + + /** +@@ -679,20 +711,27 @@ int irdma_uk_inline_rdma_write(struct irdma_qp_uk *qp, + struct irdma_post_sq_info *info, bool post_sq) + { + __le64 *wqe; +- struct irdma_inline_rdma_write *op_info; ++ struct irdma_rdma_write *op_info; + u64 hdr = 0; + u32 wqe_idx; + bool read_fence = false; ++ u32 i, total_size = 0; + u16 quanta; + + info->push_wqe = qp->push_db ? true : false; +- op_info = &info->op.inline_rdma_write; ++ op_info = &info->op.rdma_write; ++ ++ if (unlikely(qp->max_sq_frag_cnt < op_info->num_lo_sges)) ++ return -EINVAL; ++ ++ for (i = 0; i < op_info->num_lo_sges; i++) ++ total_size += op_info->lo_sg_list[i].length; + +- if (op_info->len > qp->max_inline_data) ++ if (unlikely(total_size > qp->max_inline_data)) + return -EINVAL; + +- quanta = qp->wqe_ops.iw_inline_data_size_to_quanta(op_info->len); +- wqe = irdma_qp_get_next_send_wqe(qp, &wqe_idx, quanta, op_info->len, ++ quanta = qp->wqe_ops.iw_inline_data_size_to_quanta(total_size); ++ wqe = irdma_qp_get_next_send_wqe(qp, &wqe_idx, quanta, total_size, + info); + if (!wqe) + return -ENOMEM; +@@ -705,7 +744,7 @@ int irdma_uk_inline_rdma_write(struct irdma_qp_uk *qp, + + hdr = FIELD_PREP(IRDMAQPSQ_REMSTAG, op_info->rem_addr.lkey) | + FIELD_PREP(IRDMAQPSQ_OPCODE, info->op_type) | +- FIELD_PREP(IRDMAQPSQ_INLINEDATALEN, op_info->len) | ++ FIELD_PREP(IRDMAQPSQ_INLINEDATALEN, total_size) | + FIELD_PREP(IRDMAQPSQ_REPORTRTT, info->report_rtt ? 1 : 0) | + FIELD_PREP(IRDMAQPSQ_INLINEDATAFLAG, 1) | + FIELD_PREP(IRDMAQPSQ_IMMDATAFLAG, info->imm_data_valid ? 1 : 0) | +@@ -719,7 +758,8 @@ int irdma_uk_inline_rdma_write(struct irdma_qp_uk *qp, + set_64bit_val(wqe, 0, + FIELD_PREP(IRDMAQPSQ_IMMDATA, info->imm_data)); + +- qp->wqe_ops.iw_copy_inline_data((u8 *)wqe, op_info->data, op_info->len, ++ qp->wqe_ops.iw_copy_inline_data((u8 *)wqe, op_info->lo_sg_list, ++ op_info->num_lo_sges, + qp->swqe_polarity); + dma_wmb(); /* make sure WQE is populated before valid bit is set */ + +@@ -745,20 +785,27 @@ int irdma_uk_inline_send(struct irdma_qp_uk *qp, + struct irdma_post_sq_info *info, bool post_sq) + { + __le64 *wqe; +- struct irdma_post_inline_send *op_info; ++ struct irdma_post_send *op_info; + u64 hdr; + u32 wqe_idx; + bool read_fence = false; ++ u32 i, total_size = 0; + u16 quanta; + + info->push_wqe = qp->push_db ? true : false; +- op_info = &info->op.inline_send; ++ op_info = &info->op.send; ++ ++ if (unlikely(qp->max_sq_frag_cnt < op_info->num_sges)) ++ return -EINVAL; + +- if (op_info->len > qp->max_inline_data) ++ for (i = 0; i < op_info->num_sges; i++) ++ total_size += op_info->sg_list[i].length; ++ ++ if (unlikely(total_size > qp->max_inline_data)) + return -EINVAL; + +- quanta = qp->wqe_ops.iw_inline_data_size_to_quanta(op_info->len); +- wqe = irdma_qp_get_next_send_wqe(qp, &wqe_idx, quanta, op_info->len, ++ quanta = qp->wqe_ops.iw_inline_data_size_to_quanta(total_size); ++ wqe = irdma_qp_get_next_send_wqe(qp, &wqe_idx, quanta, total_size, + info); + if (!wqe) + return -ENOMEM; +@@ -773,7 +820,7 @@ int irdma_uk_inline_send(struct irdma_qp_uk *qp, + hdr = FIELD_PREP(IRDMAQPSQ_REMSTAG, info->stag_to_inv) | + FIELD_PREP(IRDMAQPSQ_AHID, op_info->ah_id) | + FIELD_PREP(IRDMAQPSQ_OPCODE, info->op_type) | +- FIELD_PREP(IRDMAQPSQ_INLINEDATALEN, op_info->len) | ++ FIELD_PREP(IRDMAQPSQ_INLINEDATALEN, total_size) | + FIELD_PREP(IRDMAQPSQ_IMMDATAFLAG, + (info->imm_data_valid ? 1 : 0)) | + FIELD_PREP(IRDMAQPSQ_REPORTRTT, (info->report_rtt ? 1 : 0)) | +@@ -789,8 +836,8 @@ int irdma_uk_inline_send(struct irdma_qp_uk *qp, + if (info->imm_data_valid) + set_64bit_val(wqe, 0, + FIELD_PREP(IRDMAQPSQ_IMMDATA, info->imm_data)); +- qp->wqe_ops.iw_copy_inline_data((u8 *)wqe, op_info->data, op_info->len, +- qp->swqe_polarity); ++ qp->wqe_ops.iw_copy_inline_data((u8 *)wqe, op_info->sg_list, ++ op_info->num_sges, qp->swqe_polarity); + + dma_wmb(); /* make sure WQE is populated before valid bit is set */ + +@@ -1002,11 +1049,10 @@ int irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq, + __le64 *cqe; + struct irdma_qp_uk *qp; + struct irdma_ring *pring = NULL; +- u32 wqe_idx, q_type; ++ u32 wqe_idx; + int ret_code; + bool move_cq_head = true; + u8 polarity; +- u8 op_type; + bool ext_valid; + __le64 *ext_cqe; + +@@ -1074,7 +1120,7 @@ int irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq, + info->ud_vlan_valid = false; + } + +- q_type = (u8)FIELD_GET(IRDMA_CQ_SQ, qword3); ++ info->q_type = (u8)FIELD_GET(IRDMA_CQ_SQ, qword3); + info->error = (bool)FIELD_GET(IRDMA_CQ_ERROR, qword3); + info->push_dropped = (bool)FIELD_GET(IRDMACQ_PSHDROP, qword3); + info->ipv4 = (bool)FIELD_GET(IRDMACQ_IPV4, qword3); +@@ -1113,8 +1159,9 @@ int irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq, + } + wqe_idx = (u32)FIELD_GET(IRDMA_CQ_WQEIDX, qword3); + info->qp_handle = (irdma_qp_handle)(unsigned long)qp; ++ info->op_type = (u8)FIELD_GET(IRDMA_CQ_SQ, qword3); + +- if (q_type == IRDMA_CQE_QTYPE_RQ) { ++ if (info->q_type == IRDMA_CQE_QTYPE_RQ) { + u32 array_idx; + + array_idx = wqe_idx / qp->rq_wqe_size_multiplier; +@@ -1134,10 +1181,6 @@ int irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq, + + info->bytes_xfered = (u32)FIELD_GET(IRDMACQ_PAYLDLEN, qword0); + +- if (info->imm_valid) +- info->op_type = IRDMA_OP_TYPE_REC_IMM; +- else +- info->op_type = IRDMA_OP_TYPE_REC; + if (qword3 & IRDMACQ_STAG) { + info->stag_invalid_set = true; + info->inv_stag = (u32)FIELD_GET(IRDMACQ_INVSTAG, qword2); +@@ -1195,17 +1238,18 @@ int irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq, + sw_wqe = qp->sq_base[tail].elem; + get_64bit_val(sw_wqe, 24, + &wqe_qword); +- op_type = (u8)FIELD_GET(IRDMAQPSQ_OPCODE, wqe_qword); +- info->op_type = op_type; ++ info->op_type = (u8)FIELD_GET(IRDMAQPSQ_OPCODE, ++ wqe_qword); + IRDMA_RING_SET_TAIL(qp->sq_ring, + tail + qp->sq_wrtrk_array[tail].quanta); +- if (op_type != IRDMAQP_OP_NOP) { ++ if (info->op_type != IRDMAQP_OP_NOP) { + info->wr_id = qp->sq_wrtrk_array[tail].wrid; + info->bytes_xfered = qp->sq_wrtrk_array[tail].wr_len; + break; + } + } while (1); +- if (op_type == IRDMA_OP_TYPE_BIND_MW && info->minor_err == FLUSH_PROT_ERR) ++ if (info->op_type == IRDMA_OP_TYPE_BIND_MW && ++ info->minor_err == FLUSH_PROT_ERR) + info->minor_err = FLUSH_MW_BIND_ERR; + qp->sq_flush_seen = true; + if (!IRDMA_RING_MORE_WORK(qp->sq_ring)) +diff --git a/drivers/infiniband/hw/irdma/user.h b/drivers/infiniband/hw/irdma/user.h +index 2ef61923c9268..d0cdf609f5e06 100644 +--- a/drivers/infiniband/hw/irdma/user.h ++++ b/drivers/infiniband/hw/irdma/user.h +@@ -173,14 +173,6 @@ struct irdma_post_send { + u32 ah_id; + }; + +-struct irdma_post_inline_send { +- void *data; +- u32 len; +- u32 qkey; +- u32 dest_qp; +- u32 ah_id; +-}; +- + struct irdma_post_rq_info { + u64 wr_id; + struct ib_sge *sg_list; +@@ -193,12 +185,6 @@ struct irdma_rdma_write { + struct ib_sge rem_addr; + }; + +-struct irdma_inline_rdma_write { +- void *data; +- u32 len; +- struct ib_sge rem_addr; +-}; +- + struct irdma_rdma_read { + struct ib_sge *lo_sg_list; + u32 num_lo_sges; +@@ -241,8 +227,6 @@ struct irdma_post_sq_info { + struct irdma_rdma_read rdma_read; + struct irdma_bind_window bind_window; + struct irdma_inv_local_stag inv_local_stag; +- struct irdma_inline_rdma_write inline_rdma_write; +- struct irdma_post_inline_send inline_send; + } op; + }; + +@@ -261,6 +245,7 @@ struct irdma_cq_poll_info { + u16 ud_vlan; + u8 ud_smac[6]; + u8 op_type; ++ u8 q_type; + bool stag_invalid_set:1; /* or L_R_Key set */ + bool push_dropped:1; + bool error:1; +@@ -291,7 +276,8 @@ int irdma_uk_stag_local_invalidate(struct irdma_qp_uk *qp, + bool post_sq); + + struct irdma_wqe_uk_ops { +- void (*iw_copy_inline_data)(u8 *dest, u8 *src, u32 len, u8 polarity); ++ void (*iw_copy_inline_data)(u8 *dest, struct ib_sge *sge_list, ++ u32 num_sges, u8 polarity); + u16 (*iw_inline_data_size_to_quanta)(u32 data_size); + void (*iw_set_fragment)(__le64 *wqe, u32 offset, struct ib_sge *sge, + u8 valid); +diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c +index 8dfc9e154d733..445e69e864097 100644 +--- a/drivers/infiniband/hw/irdma/utils.c ++++ b/drivers/infiniband/hw/irdma/utils.c +@@ -2591,6 +2591,7 @@ void irdma_generate_flush_completions(struct irdma_qp *iwqp) + sw_wqe = qp->sq_base[wqe_idx].elem; + get_64bit_val(sw_wqe, 24, &wqe_qword); + cmpl->cpi.op_type = (u8)FIELD_GET(IRDMAQPSQ_OPCODE, IRDMAQPSQ_OPCODE); ++ cmpl->cpi.q_type = IRDMA_CQE_QTYPE_SQ; + /* remove the SQ WR by moving SQ tail*/ + IRDMA_RING_SET_TAIL(*sq_ring, + sq_ring->tail + qp->sq_wrtrk_array[sq_ring->tail].quanta); +@@ -2629,6 +2630,7 @@ void irdma_generate_flush_completions(struct irdma_qp *iwqp) + + cmpl->cpi.wr_id = qp->rq_wrid_array[wqe_idx]; + cmpl->cpi.op_type = IRDMA_OP_TYPE_REC; ++ cmpl->cpi.q_type = IRDMA_CQE_QTYPE_RQ; + /* remove the RQ WR by moving RQ tail */ + IRDMA_RING_SET_TAIL(*rq_ring, rq_ring->tail + 1); + ibdev_dbg(iwqp->iwrcq->ibcq.device, +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index a22afbb25bc58..f6973ea55eda7 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -63,36 +63,6 @@ static int irdma_query_device(struct ib_device *ibdev, + return 0; + } + +-/** +- * irdma_get_eth_speed_and_width - Get IB port speed and width from netdev speed +- * @link_speed: netdev phy link speed +- * @active_speed: IB port speed +- * @active_width: IB port width +- */ +-static void irdma_get_eth_speed_and_width(u32 link_speed, u16 *active_speed, +- u8 *active_width) +-{ +- if (link_speed <= SPEED_1000) { +- *active_width = IB_WIDTH_1X; +- *active_speed = IB_SPEED_SDR; +- } else if (link_speed <= SPEED_10000) { +- *active_width = IB_WIDTH_1X; +- *active_speed = IB_SPEED_FDR10; +- } else if (link_speed <= SPEED_20000) { +- *active_width = IB_WIDTH_4X; +- *active_speed = IB_SPEED_DDR; +- } else if (link_speed <= SPEED_25000) { +- *active_width = IB_WIDTH_1X; +- *active_speed = IB_SPEED_EDR; +- } else if (link_speed <= SPEED_40000) { +- *active_width = IB_WIDTH_4X; +- *active_speed = IB_SPEED_FDR10; +- } else { +- *active_width = IB_WIDTH_4X; +- *active_speed = IB_SPEED_EDR; +- } +-} +- + /** + * irdma_query_port - get port attributes + * @ibdev: device pointer from stack +@@ -120,8 +90,9 @@ static int irdma_query_port(struct ib_device *ibdev, u32 port, + props->state = IB_PORT_DOWN; + props->phys_state = IB_PORT_PHYS_STATE_DISABLED; + } +- irdma_get_eth_speed_and_width(SPEED_100000, &props->active_speed, +- &props->active_width); ++ ++ ib_get_eth_speed(ibdev, port, &props->active_speed, ++ &props->active_width); + + if (rdma_protocol_roce(ibdev, 1)) { + props->gid_tbl_len = 32; +@@ -1242,6 +1213,7 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr, + av->attrs = attr->ah_attr; + rdma_gid2ip((struct sockaddr *)&av->sgid_addr, &sgid_attr->gid); + rdma_gid2ip((struct sockaddr *)&av->dgid_addr, &attr->ah_attr.grh.dgid); ++ av->net_type = rdma_gid_attr_network_type(sgid_attr); + if (av->net_type == RDMA_NETWORK_IPV6) { + __be32 *daddr = + av->dgid_addr.saddr_in6.sin6_addr.in6_u.u6_addr32; +@@ -2358,9 +2330,10 @@ static bool irdma_check_mr_contiguous(struct irdma_pble_alloc *palloc, + * @rf: RDMA PCI function + * @iwmr: mr pointer for this memory registration + * @use_pbles: flag if to use pble's ++ * @lvl_1_only: request only level 1 pble if true + */ + static int irdma_setup_pbles(struct irdma_pci_f *rf, struct irdma_mr *iwmr, +- bool use_pbles) ++ bool use_pbles, bool lvl_1_only) + { + struct irdma_pbl *iwpbl = &iwmr->iwpbl; + struct irdma_pble_alloc *palloc = &iwpbl->pble_alloc; +@@ -2371,7 +2344,7 @@ static int irdma_setup_pbles(struct irdma_pci_f *rf, struct irdma_mr *iwmr, + + if (use_pbles) { + status = irdma_get_pble(rf->pble_rsrc, palloc, iwmr->page_cnt, +- false); ++ lvl_1_only); + if (status) + return status; + +@@ -2414,16 +2387,10 @@ static int irdma_handle_q_mem(struct irdma_device *iwdev, + bool ret = true; + + pg_size = iwmr->page_size; +- err = irdma_setup_pbles(iwdev->rf, iwmr, use_pbles); ++ err = irdma_setup_pbles(iwdev->rf, iwmr, use_pbles, true); + if (err) + return err; + +- if (use_pbles && palloc->level != PBLE_LEVEL_1) { +- irdma_free_pble(iwdev->rf->pble_rsrc, palloc); +- iwpbl->pbl_allocated = false; +- return -ENOMEM; +- } +- + if (use_pbles) + arr = palloc->level1.addr; + +@@ -2899,7 +2866,7 @@ static struct ib_mr *irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len, + case IRDMA_MEMREG_TYPE_MEM: + use_pbles = (iwmr->page_cnt != 1); + +- err = irdma_setup_pbles(iwdev->rf, iwmr, use_pbles); ++ err = irdma_setup_pbles(iwdev->rf, iwmr, use_pbles, false); + if (err) + goto error; + +@@ -3165,30 +3132,20 @@ static int irdma_post_send(struct ib_qp *ibqp, + info.stag_to_inv = ib_wr->ex.invalidate_rkey; + } + +- if (ib_wr->send_flags & IB_SEND_INLINE) { +- info.op.inline_send.data = (void *)(unsigned long) +- ib_wr->sg_list[0].addr; +- info.op.inline_send.len = ib_wr->sg_list[0].length; +- if (iwqp->ibqp.qp_type == IB_QPT_UD || +- iwqp->ibqp.qp_type == IB_QPT_GSI) { +- ah = to_iwah(ud_wr(ib_wr)->ah); +- info.op.inline_send.ah_id = ah->sc_ah.ah_info.ah_idx; +- info.op.inline_send.qkey = ud_wr(ib_wr)->remote_qkey; +- info.op.inline_send.dest_qp = ud_wr(ib_wr)->remote_qpn; +- } ++ info.op.send.num_sges = ib_wr->num_sge; ++ info.op.send.sg_list = ib_wr->sg_list; ++ if (iwqp->ibqp.qp_type == IB_QPT_UD || ++ iwqp->ibqp.qp_type == IB_QPT_GSI) { ++ ah = to_iwah(ud_wr(ib_wr)->ah); ++ info.op.send.ah_id = ah->sc_ah.ah_info.ah_idx; ++ info.op.send.qkey = ud_wr(ib_wr)->remote_qkey; ++ info.op.send.dest_qp = ud_wr(ib_wr)->remote_qpn; ++ } ++ ++ if (ib_wr->send_flags & IB_SEND_INLINE) + err = irdma_uk_inline_send(ukqp, &info, false); +- } else { +- info.op.send.num_sges = ib_wr->num_sge; +- info.op.send.sg_list = ib_wr->sg_list; +- if (iwqp->ibqp.qp_type == IB_QPT_UD || +- iwqp->ibqp.qp_type == IB_QPT_GSI) { +- ah = to_iwah(ud_wr(ib_wr)->ah); +- info.op.send.ah_id = ah->sc_ah.ah_info.ah_idx; +- info.op.send.qkey = ud_wr(ib_wr)->remote_qkey; +- info.op.send.dest_qp = ud_wr(ib_wr)->remote_qpn; +- } ++ else + err = irdma_uk_send(ukqp, &info, false); +- } + break; + case IB_WR_RDMA_WRITE_WITH_IMM: + if (ukqp->qp_caps & IRDMA_WRITE_WITH_IMM) { +@@ -3205,22 +3162,15 @@ static int irdma_post_send(struct ib_qp *ibqp, + else + info.op_type = IRDMA_OP_TYPE_RDMA_WRITE; + +- if (ib_wr->send_flags & IB_SEND_INLINE) { +- info.op.inline_rdma_write.data = (void *)(uintptr_t)ib_wr->sg_list[0].addr; +- info.op.inline_rdma_write.len = +- ib_wr->sg_list[0].length; +- info.op.inline_rdma_write.rem_addr.addr = +- rdma_wr(ib_wr)->remote_addr; +- info.op.inline_rdma_write.rem_addr.lkey = +- rdma_wr(ib_wr)->rkey; ++ info.op.rdma_write.num_lo_sges = ib_wr->num_sge; ++ info.op.rdma_write.lo_sg_list = ib_wr->sg_list; ++ info.op.rdma_write.rem_addr.addr = ++ rdma_wr(ib_wr)->remote_addr; ++ info.op.rdma_write.rem_addr.lkey = rdma_wr(ib_wr)->rkey; ++ if (ib_wr->send_flags & IB_SEND_INLINE) + err = irdma_uk_inline_rdma_write(ukqp, &info, false); +- } else { +- info.op.rdma_write.lo_sg_list = (void *)ib_wr->sg_list; +- info.op.rdma_write.num_lo_sges = ib_wr->num_sge; +- info.op.rdma_write.rem_addr.addr = rdma_wr(ib_wr)->remote_addr; +- info.op.rdma_write.rem_addr.lkey = rdma_wr(ib_wr)->rkey; ++ else + err = irdma_uk_rdma_write(ukqp, &info, false); +- } + break; + case IB_WR_RDMA_READ_WITH_INV: + inv_stag = true; +@@ -3380,7 +3330,6 @@ static enum ib_wc_status irdma_flush_err_to_ib_wc_status(enum irdma_flush_opcode + static void irdma_process_cqe(struct ib_wc *entry, + struct irdma_cq_poll_info *cq_poll_info) + { +- struct irdma_qp *iwqp; + struct irdma_sc_qp *qp; + + entry->wc_flags = 0; +@@ -3388,7 +3337,6 @@ static void irdma_process_cqe(struct ib_wc *entry, + entry->wr_id = cq_poll_info->wr_id; + + qp = cq_poll_info->qp_handle; +- iwqp = qp->qp_uk.back_qp; + entry->qp = qp->qp_uk.back_qp; + + if (cq_poll_info->error) { +@@ -3421,42 +3369,17 @@ static void irdma_process_cqe(struct ib_wc *entry, + } + } + +- switch (cq_poll_info->op_type) { +- case IRDMA_OP_TYPE_RDMA_WRITE: +- case IRDMA_OP_TYPE_RDMA_WRITE_SOL: +- entry->opcode = IB_WC_RDMA_WRITE; +- break; +- case IRDMA_OP_TYPE_RDMA_READ_INV_STAG: +- case IRDMA_OP_TYPE_RDMA_READ: +- entry->opcode = IB_WC_RDMA_READ; +- break; +- case IRDMA_OP_TYPE_SEND_INV: +- case IRDMA_OP_TYPE_SEND_SOL: +- case IRDMA_OP_TYPE_SEND_SOL_INV: +- case IRDMA_OP_TYPE_SEND: +- entry->opcode = IB_WC_SEND; +- break; +- case IRDMA_OP_TYPE_FAST_REG_NSMR: +- entry->opcode = IB_WC_REG_MR; +- break; +- case IRDMA_OP_TYPE_INV_STAG: +- entry->opcode = IB_WC_LOCAL_INV; +- break; +- case IRDMA_OP_TYPE_REC_IMM: +- case IRDMA_OP_TYPE_REC: +- entry->opcode = cq_poll_info->op_type == IRDMA_OP_TYPE_REC_IMM ? +- IB_WC_RECV_RDMA_WITH_IMM : IB_WC_RECV; ++ if (cq_poll_info->q_type == IRDMA_CQE_QTYPE_SQ) { ++ set_ib_wc_op_sq(cq_poll_info, entry); ++ } else { ++ set_ib_wc_op_rq(cq_poll_info, entry, ++ qp->qp_uk.qp_caps & IRDMA_SEND_WITH_IMM ? ++ true : false); + if (qp->qp_uk.qp_type != IRDMA_QP_TYPE_ROCE_UD && + cq_poll_info->stag_invalid_set) { + entry->ex.invalidate_rkey = cq_poll_info->inv_stag; + entry->wc_flags |= IB_WC_WITH_INVALIDATE; + } +- break; +- default: +- ibdev_err(&iwqp->iwdev->ibdev, +- "Invalid opcode = %d in CQE\n", cq_poll_info->op_type); +- entry->status = IB_WC_GENERAL_ERR; +- return; + } + + if (qp->qp_uk.qp_type == IRDMA_QP_TYPE_ROCE_UD) { +diff --git a/drivers/infiniband/hw/irdma/verbs.h b/drivers/infiniband/hw/irdma/verbs.h +index 4309b7159f42c..a536e9fa85ebf 100644 +--- a/drivers/infiniband/hw/irdma/verbs.h ++++ b/drivers/infiniband/hw/irdma/verbs.h +@@ -232,6 +232,59 @@ static inline u16 irdma_fw_minor_ver(struct irdma_sc_dev *dev) + return (u16)FIELD_GET(IRDMA_FW_VER_MINOR, dev->feature_info[IRDMA_FEATURE_FW_INFO]); + } + ++static inline void set_ib_wc_op_sq(struct irdma_cq_poll_info *cq_poll_info, ++ struct ib_wc *entry) ++{ ++ switch (cq_poll_info->op_type) { ++ case IRDMA_OP_TYPE_RDMA_WRITE: ++ case IRDMA_OP_TYPE_RDMA_WRITE_SOL: ++ entry->opcode = IB_WC_RDMA_WRITE; ++ break; ++ case IRDMA_OP_TYPE_RDMA_READ_INV_STAG: ++ case IRDMA_OP_TYPE_RDMA_READ: ++ entry->opcode = IB_WC_RDMA_READ; ++ break; ++ case IRDMA_OP_TYPE_SEND_SOL: ++ case IRDMA_OP_TYPE_SEND_SOL_INV: ++ case IRDMA_OP_TYPE_SEND_INV: ++ case IRDMA_OP_TYPE_SEND: ++ entry->opcode = IB_WC_SEND; ++ break; ++ case IRDMA_OP_TYPE_FAST_REG_NSMR: ++ entry->opcode = IB_WC_REG_MR; ++ break; ++ case IRDMA_OP_TYPE_INV_STAG: ++ entry->opcode = IB_WC_LOCAL_INV; ++ break; ++ default: ++ entry->status = IB_WC_GENERAL_ERR; ++ } ++} ++ ++static inline void set_ib_wc_op_rq(struct irdma_cq_poll_info *cq_poll_info, ++ struct ib_wc *entry, bool send_imm_support) ++{ ++ /** ++ * iWARP does not support sendImm, so the presence of Imm data ++ * must be WriteImm. ++ */ ++ if (!send_imm_support) { ++ entry->opcode = cq_poll_info->imm_valid ? ++ IB_WC_RECV_RDMA_WITH_IMM : ++ IB_WC_RECV; ++ return; ++ } ++ ++ switch (cq_poll_info->op_type) { ++ case IB_OPCODE_RDMA_WRITE_ONLY_WITH_IMMEDIATE: ++ case IB_OPCODE_RDMA_WRITE_LAST_WITH_IMMEDIATE: ++ entry->opcode = IB_WC_RECV_RDMA_WITH_IMM; ++ break; ++ default: ++ entry->opcode = IB_WC_RECV; ++ } ++} ++ + void irdma_mcast_mac(u32 *ip_addr, u8 *mac, bool ipv4); + int irdma_ib_register_device(struct irdma_device *iwdev); + void irdma_ib_unregister_device(struct irdma_device *iwdev); +diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c +index 502e9ada99b30..80e2d631fdb24 100644 +--- a/drivers/infiniband/sw/rxe/rxe_mr.c ++++ b/drivers/infiniband/sw/rxe/rxe_mr.c +@@ -99,6 +99,7 @@ err2: + kfree(mr->map[i]); + + kfree(mr->map); ++ mr->map = NULL; + err1: + return -ENOMEM; + } +@@ -122,7 +123,6 @@ int rxe_mr_init_user(struct rxe_dev *rxe, u64 start, u64 length, u64 iova, + int num_buf; + void *vaddr; + int err; +- int i; + + umem = ib_umem_get(&rxe->ib_dev, start, length, access); + if (IS_ERR(umem)) { +@@ -163,9 +163,8 @@ int rxe_mr_init_user(struct rxe_dev *rxe, u64 start, u64 length, u64 iova, + pr_warn("%s: Unable to get virtual address\n", + __func__); + err = -ENOMEM; +- goto err_cleanup_map; ++ goto err_release_umem; + } +- + buf->addr = (uintptr_t)vaddr; + buf->size = PAGE_SIZE; + num_buf++; +@@ -182,10 +181,6 @@ int rxe_mr_init_user(struct rxe_dev *rxe, u64 start, u64 length, u64 iova, + + return 0; + +-err_cleanup_map: +- for (i = 0; i < mr->num_map; i++) +- kfree(mr->map[i]); +- kfree(mr->map); + err_release_umem: + ib_umem_release(umem); + err_out: +diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c +index a62bab88415cb..e459fb542b83a 100644 +--- a/drivers/infiniband/sw/rxe/rxe_qp.c ++++ b/drivers/infiniband/sw/rxe/rxe_qp.c +@@ -829,12 +829,12 @@ static void rxe_qp_do_cleanup(struct work_struct *work) + if (qp->resp.mr) + rxe_put(qp->resp.mr); + +- if (qp_type(qp) == IB_QPT_RC) +- sk_dst_reset(qp->sk->sk); +- + free_rd_atomic_resources(qp); + + if (qp->sk) { ++ if (qp_type(qp) == IB_QPT_RC) ++ sk_dst_reset(qp->sk->sk); ++ + kernel_sock_shutdown(qp->sk, SHUT_RDWR); + sock_release(qp->sk); + } +diff --git a/drivers/infiniband/sw/siw/siw_cq.c b/drivers/infiniband/sw/siw/siw_cq.c +index d68e37859e73b..403029de6b92d 100644 +--- a/drivers/infiniband/sw/siw/siw_cq.c ++++ b/drivers/infiniband/sw/siw/siw_cq.c +@@ -56,8 +56,6 @@ int siw_reap_cqe(struct siw_cq *cq, struct ib_wc *wc) + if (READ_ONCE(cqe->flags) & SIW_WQE_VALID) { + memset(wc, 0, sizeof(*wc)); + wc->wr_id = cqe->id; +- wc->status = map_cqe_status[cqe->status].ib; +- wc->opcode = map_wc_opcode[cqe->opcode]; + wc->byte_len = cqe->bytes; + + /* +@@ -71,10 +69,32 @@ int siw_reap_cqe(struct siw_cq *cq, struct ib_wc *wc) + wc->wc_flags = IB_WC_WITH_INVALIDATE; + } + wc->qp = cqe->base_qp; ++ wc->opcode = map_wc_opcode[cqe->opcode]; ++ wc->status = map_cqe_status[cqe->status].ib; + siw_dbg_cq(cq, + "idx %u, type %d, flags %2x, id 0x%pK\n", + cq->cq_get % cq->num_cqe, cqe->opcode, + cqe->flags, (void *)(uintptr_t)cqe->id); ++ } else { ++ /* ++ * A malicious user may set invalid opcode or ++ * status in the user mmapped CQE array. ++ * Sanity check and correct values in that case ++ * to avoid out-of-bounds access to global arrays ++ * for opcode and status mapping. ++ */ ++ u8 opcode = cqe->opcode; ++ u16 status = cqe->status; ++ ++ if (opcode >= SIW_NUM_OPCODES) { ++ opcode = 0; ++ status = SIW_WC_GENERAL_ERR; ++ } else if (status >= SIW_NUM_WC_STATUS) { ++ status = SIW_WC_GENERAL_ERR; ++ } ++ wc->opcode = map_wc_opcode[opcode]; ++ wc->status = map_cqe_status[status].ib; ++ + } + WRITE_ONCE(cqe->flags, 0); + cq->cq_get++; +diff --git a/drivers/infiniband/sw/siw/siw_qp_tx.c b/drivers/infiniband/sw/siw/siw_qp_tx.c +index 7d47b521070b1..05052b49107f2 100644 +--- a/drivers/infiniband/sw/siw/siw_qp_tx.c ++++ b/drivers/infiniband/sw/siw/siw_qp_tx.c +@@ -29,7 +29,7 @@ static struct page *siw_get_pblpage(struct siw_mem *mem, u64 addr, int *idx) + dma_addr_t paddr = siw_pbl_get_buffer(pbl, offset, NULL, idx); + + if (paddr) +- return virt_to_page((void *)paddr); ++ return virt_to_page((void *)(uintptr_t)paddr); + + return NULL; + } +diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c +index 3e814cfb298cf..906fde1a2a0de 100644 +--- a/drivers/infiniband/sw/siw/siw_verbs.c ++++ b/drivers/infiniband/sw/siw/siw_verbs.c +@@ -676,13 +676,45 @@ static int siw_copy_inline_sgl(const struct ib_send_wr *core_wr, + static int siw_sq_flush_wr(struct siw_qp *qp, const struct ib_send_wr *wr, + const struct ib_send_wr **bad_wr) + { +- struct siw_sqe sqe = {}; + int rv = 0; + + while (wr) { +- sqe.id = wr->wr_id; +- sqe.opcode = wr->opcode; +- rv = siw_sqe_complete(qp, &sqe, 0, SIW_WC_WR_FLUSH_ERR); ++ struct siw_sqe sqe = {}; ++ ++ switch (wr->opcode) { ++ case IB_WR_RDMA_WRITE: ++ sqe.opcode = SIW_OP_WRITE; ++ break; ++ case IB_WR_RDMA_READ: ++ sqe.opcode = SIW_OP_READ; ++ break; ++ case IB_WR_RDMA_READ_WITH_INV: ++ sqe.opcode = SIW_OP_READ_LOCAL_INV; ++ break; ++ case IB_WR_SEND: ++ sqe.opcode = SIW_OP_SEND; ++ break; ++ case IB_WR_SEND_WITH_IMM: ++ sqe.opcode = SIW_OP_SEND_WITH_IMM; ++ break; ++ case IB_WR_SEND_WITH_INV: ++ sqe.opcode = SIW_OP_SEND_REMOTE_INV; ++ break; ++ case IB_WR_LOCAL_INV: ++ sqe.opcode = SIW_OP_INVAL_STAG; ++ break; ++ case IB_WR_REG_MR: ++ sqe.opcode = SIW_OP_REG_MR; ++ break; ++ default: ++ rv = -EINVAL; ++ break; ++ } ++ if (!rv) { ++ sqe.id = wr->wr_id; ++ rv = siw_sqe_complete(qp, &sqe, 0, ++ SIW_WC_WR_FLUSH_ERR); ++ } + if (rv) { + if (bad_wr) + *bad_wr = wr; +diff --git a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c +index ea16ba5d8da6c..9ad8d98562752 100644 +--- a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c ++++ b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c +@@ -41,6 +41,11 @@ static const struct nla_policy ipoib_policy[IFLA_IPOIB_MAX + 1] = { + [IFLA_IPOIB_UMCAST] = { .type = NLA_U16 }, + }; + ++static unsigned int ipoib_get_max_num_queues(void) ++{ ++ return min_t(unsigned int, num_possible_cpus(), 128); ++} ++ + static int ipoib_fill_info(struct sk_buff *skb, const struct net_device *dev) + { + struct ipoib_dev_priv *priv = ipoib_priv(dev); +@@ -172,6 +177,8 @@ static struct rtnl_link_ops ipoib_link_ops __read_mostly = { + .changelink = ipoib_changelink, + .get_size = ipoib_get_size, + .fill_info = ipoib_fill_info, ++ .get_num_rx_queues = ipoib_get_max_num_queues, ++ .get_num_tx_queues = ipoib_get_max_num_queues, + }; + + struct rtnl_link_ops *ipoib_get_link_ops(void) +diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c +index 1075c2ac8fe20..b4d6a4a5ae81e 100644 +--- a/drivers/infiniband/ulp/srp/ib_srp.c ++++ b/drivers/infiniband/ulp/srp/ib_srp.c +@@ -3410,7 +3410,8 @@ static int srp_parse_options(struct net *net, const char *buf, + break; + + case SRP_OPT_PKEY: +- if (match_hex(args, &token)) { ++ ret = match_hex(args, &token); ++ if (ret) { + pr_warn("bad P_Key parameter '%s'\n", p); + goto out; + } +@@ -3470,7 +3471,8 @@ static int srp_parse_options(struct net *net, const char *buf, + break; + + case SRP_OPT_MAX_SECT: +- if (match_int(args, &token)) { ++ ret = match_int(args, &token); ++ if (ret) { + pr_warn("bad max sect parameter '%s'\n", p); + goto out; + } +@@ -3478,8 +3480,15 @@ static int srp_parse_options(struct net *net, const char *buf, + break; + + case SRP_OPT_QUEUE_SIZE: +- if (match_int(args, &token) || token < 1) { ++ ret = match_int(args, &token); ++ if (ret) { ++ pr_warn("match_int() failed for queue_size parameter '%s', Error %d\n", ++ p, ret); ++ goto out; ++ } ++ if (token < 1) { + pr_warn("bad queue_size parameter '%s'\n", p); ++ ret = -EINVAL; + goto out; + } + target->scsi_host->can_queue = token; +@@ -3490,25 +3499,40 @@ static int srp_parse_options(struct net *net, const char *buf, + break; + + case SRP_OPT_MAX_CMD_PER_LUN: +- if (match_int(args, &token) || token < 1) { ++ ret = match_int(args, &token); ++ if (ret) { ++ pr_warn("match_int() failed for max cmd_per_lun parameter '%s', Error %d\n", ++ p, ret); ++ goto out; ++ } ++ if (token < 1) { + pr_warn("bad max cmd_per_lun parameter '%s'\n", + p); ++ ret = -EINVAL; + goto out; + } + target->scsi_host->cmd_per_lun = token; + break; + + case SRP_OPT_TARGET_CAN_QUEUE: +- if (match_int(args, &token) || token < 1) { ++ ret = match_int(args, &token); ++ if (ret) { ++ pr_warn("match_int() failed for max target_can_queue parameter '%s', Error %d\n", ++ p, ret); ++ goto out; ++ } ++ if (token < 1) { + pr_warn("bad max target_can_queue parameter '%s'\n", + p); ++ ret = -EINVAL; + goto out; + } + target->target_can_queue = token; + break; + + case SRP_OPT_IO_CLASS: +- if (match_hex(args, &token)) { ++ ret = match_hex(args, &token); ++ if (ret) { + pr_warn("bad IO class parameter '%s'\n", p); + goto out; + } +@@ -3517,6 +3541,7 @@ static int srp_parse_options(struct net *net, const char *buf, + pr_warn("unknown IO class parameter value %x specified (use %x or %x).\n", + token, SRP_REV10_IB_IO_CLASS, + SRP_REV16A_IB_IO_CLASS); ++ ret = -EINVAL; + goto out; + } + target->io_class = token; +@@ -3539,16 +3564,24 @@ static int srp_parse_options(struct net *net, const char *buf, + break; + + case SRP_OPT_CMD_SG_ENTRIES: +- if (match_int(args, &token) || token < 1 || token > 255) { ++ ret = match_int(args, &token); ++ if (ret) { ++ pr_warn("match_int() failed for max cmd_sg_entries parameter '%s', Error %d\n", ++ p, ret); ++ goto out; ++ } ++ if (token < 1 || token > 255) { + pr_warn("bad max cmd_sg_entries parameter '%s'\n", + p); ++ ret = -EINVAL; + goto out; + } + target->cmd_sg_cnt = token; + break; + + case SRP_OPT_ALLOW_EXT_SG: +- if (match_int(args, &token)) { ++ ret = match_int(args, &token); ++ if (ret) { + pr_warn("bad allow_ext_sg parameter '%s'\n", p); + goto out; + } +@@ -3556,43 +3589,77 @@ static int srp_parse_options(struct net *net, const char *buf, + break; + + case SRP_OPT_SG_TABLESIZE: +- if (match_int(args, &token) || token < 1 || +- token > SG_MAX_SEGMENTS) { ++ ret = match_int(args, &token); ++ if (ret) { ++ pr_warn("match_int() failed for max sg_tablesize parameter '%s', Error %d\n", ++ p, ret); ++ goto out; ++ } ++ if (token < 1 || token > SG_MAX_SEGMENTS) { + pr_warn("bad max sg_tablesize parameter '%s'\n", + p); ++ ret = -EINVAL; + goto out; + } + target->sg_tablesize = token; + break; + + case SRP_OPT_COMP_VECTOR: +- if (match_int(args, &token) || token < 0) { ++ ret = match_int(args, &token); ++ if (ret) { ++ pr_warn("match_int() failed for comp_vector parameter '%s', Error %d\n", ++ p, ret); ++ goto out; ++ } ++ if (token < 0) { + pr_warn("bad comp_vector parameter '%s'\n", p); ++ ret = -EINVAL; + goto out; + } + target->comp_vector = token; + break; + + case SRP_OPT_TL_RETRY_COUNT: +- if (match_int(args, &token) || token < 2 || token > 7) { ++ ret = match_int(args, &token); ++ if (ret) { ++ pr_warn("match_int() failed for tl_retry_count parameter '%s', Error %d\n", ++ p, ret); ++ goto out; ++ } ++ if (token < 2 || token > 7) { + pr_warn("bad tl_retry_count parameter '%s' (must be a number between 2 and 7)\n", + p); ++ ret = -EINVAL; + goto out; + } + target->tl_retry_count = token; + break; + + case SRP_OPT_MAX_IT_IU_SIZE: +- if (match_int(args, &token) || token < 0) { ++ ret = match_int(args, &token); ++ if (ret) { ++ pr_warn("match_int() failed for max it_iu_size parameter '%s', Error %d\n", ++ p, ret); ++ goto out; ++ } ++ if (token < 0) { + pr_warn("bad maximum initiator to target IU size '%s'\n", p); ++ ret = -EINVAL; + goto out; + } + target->max_it_iu_size = token; + break; + + case SRP_OPT_CH_COUNT: +- if (match_int(args, &token) || token < 1) { ++ ret = match_int(args, &token); ++ if (ret) { ++ pr_warn("match_int() failed for channel count parameter '%s', Error %d\n", ++ p, ret); ++ goto out; ++ } ++ if (token < 1) { + pr_warn("bad channel count %s\n", p); ++ ret = -EINVAL; + goto out; + } + target->ch_count = token; +@@ -3601,6 +3668,7 @@ static int srp_parse_options(struct net *net, const char *buf, + default: + pr_warn("unknown parameter or missing value '%s' in target creation request\n", + p); ++ ret = -EINVAL; + goto out; + } + } +diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig +index 9dcf3f51f2dd9..04ca3d1c28162 100644 +--- a/drivers/input/joystick/Kconfig ++++ b/drivers/input/joystick/Kconfig +@@ -46,6 +46,7 @@ config JOYSTICK_A3D + config JOYSTICK_ADC + tristate "Simple joystick connected over ADC" + depends on IIO ++ select IIO_BUFFER + select IIO_BUFFER_CB + help + Say Y here if you have a simple joystick connected over ADC. +diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig +index 9f088900f863b..fa942651619d2 100644 +--- a/drivers/input/misc/Kconfig ++++ b/drivers/input/misc/Kconfig +@@ -330,7 +330,7 @@ config INPUT_CPCAP_PWRBUTTON + + config INPUT_WISTRON_BTNS + tristate "x86 Wistron laptop button interface" +- depends on X86_32 ++ depends on X86_32 && !UML + select INPUT_SPARSEKMAP + select NEW_LEDS + select LEDS_CLASS +diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c +index ddb863bf63eec..e47ab6c1177f5 100644 +--- a/drivers/input/misc/iqs7222.c ++++ b/drivers/input/misc/iqs7222.c +@@ -86,7 +86,9 @@ enum iqs7222_reg_key_id { + IQS7222_REG_KEY_TOUCH, + IQS7222_REG_KEY_DEBOUNCE, + IQS7222_REG_KEY_TAP, ++ IQS7222_REG_KEY_TAP_LEGACY, + IQS7222_REG_KEY_AXIAL, ++ IQS7222_REG_KEY_AXIAL_LEGACY, + IQS7222_REG_KEY_WHEEL, + IQS7222_REG_KEY_NO_WHEEL, + IQS7222_REG_KEY_RESERVED +@@ -105,14 +107,14 @@ enum iqs7222_reg_grp_id { + IQS7222_NUM_REG_GRPS + }; + +-static const char * const iqs7222_reg_grp_names[] = { ++static const char * const iqs7222_reg_grp_names[IQS7222_NUM_REG_GRPS] = { + [IQS7222_REG_GRP_CYCLE] = "cycle", + [IQS7222_REG_GRP_CHAN] = "channel", + [IQS7222_REG_GRP_SLDR] = "slider", + [IQS7222_REG_GRP_GPIO] = "gpio", + }; + +-static const unsigned int iqs7222_max_cols[] = { ++static const unsigned int iqs7222_max_cols[IQS7222_NUM_REG_GRPS] = { + [IQS7222_REG_GRP_STAT] = IQS7222_MAX_COLS_STAT, + [IQS7222_REG_GRP_CYCLE] = IQS7222_MAX_COLS_CYCLE, + [IQS7222_REG_GRP_GLBL] = IQS7222_MAX_COLS_GLBL, +@@ -202,10 +204,68 @@ struct iqs7222_dev_desc { + int allow_offset; + int event_offset; + int comms_offset; ++ bool legacy_gesture; + struct iqs7222_reg_grp_desc reg_grps[IQS7222_NUM_REG_GRPS]; + }; + + static const struct iqs7222_dev_desc iqs7222_devs[] = { ++ { ++ .prod_num = IQS7222_PROD_NUM_A, ++ .fw_major = 1, ++ .fw_minor = 13, ++ .sldr_res = U8_MAX * 16, ++ .touch_link = 1768, ++ .allow_offset = 9, ++ .event_offset = 10, ++ .comms_offset = 12, ++ .reg_grps = { ++ [IQS7222_REG_GRP_STAT] = { ++ .base = IQS7222_SYS_STATUS, ++ .num_row = 1, ++ .num_col = 8, ++ }, ++ [IQS7222_REG_GRP_CYCLE] = { ++ .base = 0x8000, ++ .num_row = 7, ++ .num_col = 3, ++ }, ++ [IQS7222_REG_GRP_GLBL] = { ++ .base = 0x8700, ++ .num_row = 1, ++ .num_col = 3, ++ }, ++ [IQS7222_REG_GRP_BTN] = { ++ .base = 0x9000, ++ .num_row = 12, ++ .num_col = 3, ++ }, ++ [IQS7222_REG_GRP_CHAN] = { ++ .base = 0xA000, ++ .num_row = 12, ++ .num_col = 6, ++ }, ++ [IQS7222_REG_GRP_FILT] = { ++ .base = 0xAC00, ++ .num_row = 1, ++ .num_col = 2, ++ }, ++ [IQS7222_REG_GRP_SLDR] = { ++ .base = 0xB000, ++ .num_row = 2, ++ .num_col = 11, ++ }, ++ [IQS7222_REG_GRP_GPIO] = { ++ .base = 0xC000, ++ .num_row = 1, ++ .num_col = 3, ++ }, ++ [IQS7222_REG_GRP_SYS] = { ++ .base = IQS7222_SYS_SETUP, ++ .num_row = 1, ++ .num_col = 13, ++ }, ++ }, ++ }, + { + .prod_num = IQS7222_PROD_NUM_A, + .fw_major = 1, +@@ -215,6 +275,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { + .allow_offset = 9, + .event_offset = 10, + .comms_offset = 12, ++ .legacy_gesture = true, + .reg_grps = { + [IQS7222_REG_GRP_STAT] = { + .base = IQS7222_SYS_STATUS, +@@ -874,6 +935,16 @@ static const struct iqs7222_prop_desc iqs7222_props[] = { + .reg_offset = 9, + .reg_shift = 8, + .reg_width = 8, ++ .val_pitch = 16, ++ .label = "maximum gesture time", ++ }, ++ { ++ .name = "azoteq,gesture-max-ms", ++ .reg_grp = IQS7222_REG_GRP_SLDR, ++ .reg_key = IQS7222_REG_KEY_TAP_LEGACY, ++ .reg_offset = 9, ++ .reg_shift = 8, ++ .reg_width = 8, + .val_pitch = 4, + .label = "maximum gesture time", + }, +@@ -884,6 +955,16 @@ static const struct iqs7222_prop_desc iqs7222_props[] = { + .reg_offset = 9, + .reg_shift = 3, + .reg_width = 5, ++ .val_pitch = 16, ++ .label = "minimum gesture time", ++ }, ++ { ++ .name = "azoteq,gesture-min-ms", ++ .reg_grp = IQS7222_REG_GRP_SLDR, ++ .reg_key = IQS7222_REG_KEY_TAP_LEGACY, ++ .reg_offset = 9, ++ .reg_shift = 3, ++ .reg_width = 5, + .val_pitch = 4, + .label = "minimum gesture time", + }, +@@ -897,6 +978,16 @@ static const struct iqs7222_prop_desc iqs7222_props[] = { + .val_pitch = 16, + .label = "gesture distance", + }, ++ { ++ .name = "azoteq,gesture-dist", ++ .reg_grp = IQS7222_REG_GRP_SLDR, ++ .reg_key = IQS7222_REG_KEY_AXIAL_LEGACY, ++ .reg_offset = 10, ++ .reg_shift = 8, ++ .reg_width = 8, ++ .val_pitch = 16, ++ .label = "gesture distance", ++ }, + { + .name = "azoteq,gesture-max-ms", + .reg_grp = IQS7222_REG_GRP_SLDR, +@@ -904,6 +995,16 @@ static const struct iqs7222_prop_desc iqs7222_props[] = { + .reg_offset = 10, + .reg_shift = 0, + .reg_width = 8, ++ .val_pitch = 16, ++ .label = "maximum gesture time", ++ }, ++ { ++ .name = "azoteq,gesture-max-ms", ++ .reg_grp = IQS7222_REG_GRP_SLDR, ++ .reg_key = IQS7222_REG_KEY_AXIAL_LEGACY, ++ .reg_offset = 10, ++ .reg_shift = 0, ++ .reg_width = 8, + .val_pitch = 4, + .label = "maximum gesture time", + }, +@@ -1567,56 +1668,17 @@ static int iqs7222_gpio_select(struct iqs7222_private *iqs7222, + } + + static int iqs7222_parse_props(struct iqs7222_private *iqs7222, +- struct fwnode_handle **child_node, +- int child_index, ++ struct fwnode_handle *reg_grp_node, ++ int reg_grp_index, + enum iqs7222_reg_grp_id reg_grp, + enum iqs7222_reg_key_id reg_key) + { +- u16 *setup = iqs7222_setup(iqs7222, reg_grp, child_index); ++ u16 *setup = iqs7222_setup(iqs7222, reg_grp, reg_grp_index); + struct i2c_client *client = iqs7222->client; +- struct fwnode_handle *reg_grp_node; +- char reg_grp_name[16]; + int i; + +- switch (reg_grp) { +- case IQS7222_REG_GRP_CYCLE: +- case IQS7222_REG_GRP_CHAN: +- case IQS7222_REG_GRP_SLDR: +- case IQS7222_REG_GRP_GPIO: +- case IQS7222_REG_GRP_BTN: +- /* +- * These groups derive a child node and return it to the caller +- * for additional group-specific processing. In some cases, the +- * child node may have already been derived. +- */ +- reg_grp_node = *child_node; +- if (reg_grp_node) +- break; +- +- snprintf(reg_grp_name, sizeof(reg_grp_name), "%s-%d", +- iqs7222_reg_grp_names[reg_grp], child_index); +- +- reg_grp_node = device_get_named_child_node(&client->dev, +- reg_grp_name); +- if (!reg_grp_node) +- return 0; +- +- *child_node = reg_grp_node; +- break; +- +- case IQS7222_REG_GRP_GLBL: +- case IQS7222_REG_GRP_FILT: +- case IQS7222_REG_GRP_SYS: +- /* +- * These groups are not organized beneath a child node, nor are +- * they subject to any additional processing by the caller. +- */ +- reg_grp_node = dev_fwnode(&client->dev); +- break; +- +- default: +- return -EINVAL; +- } ++ if (!setup) ++ return 0; + + for (i = 0; i < ARRAY_SIZE(iqs7222_props); i++) { + const char *name = iqs7222_props[i].name; +@@ -1686,11 +1748,66 @@ static int iqs7222_parse_props(struct iqs7222_private *iqs7222, + return 0; + } + +-static int iqs7222_parse_cycle(struct iqs7222_private *iqs7222, int cycle_index) ++static int iqs7222_parse_event(struct iqs7222_private *iqs7222, ++ struct fwnode_handle *event_node, ++ int reg_grp_index, ++ enum iqs7222_reg_grp_id reg_grp, ++ enum iqs7222_reg_key_id reg_key, ++ u16 event_enable, u16 event_link, ++ unsigned int *event_type, ++ unsigned int *event_code) ++{ ++ struct i2c_client *client = iqs7222->client; ++ int error; ++ ++ error = iqs7222_parse_props(iqs7222, event_node, reg_grp_index, ++ reg_grp, reg_key); ++ if (error) ++ return error; ++ ++ error = iqs7222_gpio_select(iqs7222, event_node, event_enable, ++ event_link); ++ if (error) ++ return error; ++ ++ error = fwnode_property_read_u32(event_node, "linux,code", event_code); ++ if (error == -EINVAL) { ++ return 0; ++ } else if (error) { ++ dev_err(&client->dev, "Failed to read %s code: %d\n", ++ fwnode_get_name(event_node), error); ++ return error; ++ } ++ ++ if (!event_type) { ++ input_set_capability(iqs7222->keypad, EV_KEY, *event_code); ++ return 0; ++ } ++ ++ error = fwnode_property_read_u32(event_node, "linux,input-type", ++ event_type); ++ if (error == -EINVAL) { ++ *event_type = EV_KEY; ++ } else if (error) { ++ dev_err(&client->dev, "Failed to read %s input type: %d\n", ++ fwnode_get_name(event_node), error); ++ return error; ++ } else if (*event_type != EV_KEY && *event_type != EV_SW) { ++ dev_err(&client->dev, "Invalid %s input type: %d\n", ++ fwnode_get_name(event_node), *event_type); ++ return -EINVAL; ++ } ++ ++ input_set_capability(iqs7222->keypad, *event_type, *event_code); ++ ++ return 0; ++} ++ ++static int iqs7222_parse_cycle(struct iqs7222_private *iqs7222, ++ struct fwnode_handle *cycle_node, int cycle_index) + { + u16 *cycle_setup = iqs7222->cycle_setup[cycle_index]; + struct i2c_client *client = iqs7222->client; +- struct fwnode_handle *cycle_node = NULL; + unsigned int pins[9]; + int error, count, i; + +@@ -1698,17 +1815,7 @@ static int iqs7222_parse_cycle(struct iqs7222_private *iqs7222, int cycle_index) + * Each channel shares a cycle with one other channel; the mapping of + * channels to cycles is fixed. Properties defined for a cycle impact + * both channels tied to the cycle. +- */ +- error = iqs7222_parse_props(iqs7222, &cycle_node, cycle_index, +- IQS7222_REG_GRP_CYCLE, +- IQS7222_REG_KEY_NONE); +- if (error) +- return error; +- +- if (!cycle_node) +- return 0; +- +- /* ++ * + * Unlike channels which are restricted to a select range of CRx pins + * based on channel number, any cycle can claim any of the device's 9 + * CTx pins (CTx0-8). +@@ -1750,11 +1857,11 @@ static int iqs7222_parse_cycle(struct iqs7222_private *iqs7222, int cycle_index) + return 0; + } + +-static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index) ++static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, ++ struct fwnode_handle *chan_node, int chan_index) + { + const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc; + struct i2c_client *client = iqs7222->client; +- struct fwnode_handle *chan_node = NULL; + int num_chan = dev_desc->reg_grps[IQS7222_REG_GRP_CHAN].num_row; + int ext_chan = rounddown(num_chan, 10); + int error, i; +@@ -1762,15 +1869,6 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index) + u16 *sys_setup = iqs7222->sys_setup; + unsigned int val; + +- error = iqs7222_parse_props(iqs7222, &chan_node, chan_index, +- IQS7222_REG_GRP_CHAN, +- IQS7222_REG_KEY_NONE); +- if (error) +- return error; +- +- if (!chan_node) +- return 0; +- + if (dev_desc->allow_offset && + fwnode_property_present(chan_node, "azoteq,ulp-allow")) + sys_setup[dev_desc->allow_offset] &= ~BIT(chan_index); +@@ -1810,8 +1908,9 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index) + chan_setup[0] |= IQS7222_CHAN_SETUP_0_REF_MODE_FOLLOW; + chan_setup[4] = val * 42 + 1048; + +- if (!fwnode_property_read_u32(chan_node, "azoteq,ref-weight", +- &val)) { ++ error = fwnode_property_read_u32(chan_node, "azoteq,ref-weight", ++ &val); ++ if (!error) { + if (val > U16_MAX) { + dev_err(&client->dev, + "Invalid %s reference weight: %u\n", +@@ -1820,6 +1919,11 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index) + } + + chan_setup[5] = val; ++ } else if (error != -EINVAL) { ++ dev_err(&client->dev, ++ "Failed to read %s reference weight: %d\n", ++ fwnode_get_name(chan_node), error); ++ return error; + } + + /* +@@ -1892,21 +1996,10 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index) + if (!event_node) + continue; + +- error = iqs7222_parse_props(iqs7222, &event_node, chan_index, +- IQS7222_REG_GRP_BTN, +- iqs7222_kp_events[i].reg_key); +- if (error) +- return error; +- +- error = iqs7222_gpio_select(iqs7222, event_node, +- BIT(chan_index), +- dev_desc->touch_link - (i ? 0 : 2)); +- if (error) +- return error; +- +- if (!fwnode_property_read_u32(event_node, +- "azoteq,timeout-press-ms", +- &val)) { ++ error = fwnode_property_read_u32(event_node, ++ "azoteq,timeout-press-ms", ++ &val); ++ if (!error) { + /* + * The IQS7222B employs a global pair of press timeout + * registers as opposed to channel-specific registers. +@@ -1919,57 +2012,31 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index) + if (val > U8_MAX * 500) { + dev_err(&client->dev, + "Invalid %s press timeout: %u\n", +- fwnode_get_name(chan_node), val); ++ fwnode_get_name(event_node), val); ++ fwnode_handle_put(event_node); + return -EINVAL; + } + + *setup &= ~(U8_MAX << i * 8); + *setup |= (val / 500 << i * 8); +- } +- +- error = fwnode_property_read_u32(event_node, "linux,code", +- &val); +- if (error) { +- dev_err(&client->dev, "Failed to read %s code: %d\n", +- fwnode_get_name(chan_node), error); ++ } else if (error != -EINVAL) { ++ dev_err(&client->dev, ++ "Failed to read %s press timeout: %d\n", ++ fwnode_get_name(event_node), error); ++ fwnode_handle_put(event_node); + return error; + } + +- iqs7222->kp_code[chan_index][i] = val; +- iqs7222->kp_type[chan_index][i] = EV_KEY; +- +- if (fwnode_property_present(event_node, "linux,input-type")) { +- error = fwnode_property_read_u32(event_node, +- "linux,input-type", +- &val); +- if (error) { +- dev_err(&client->dev, +- "Failed to read %s input type: %d\n", +- fwnode_get_name(chan_node), error); +- return error; +- } +- +- if (val != EV_KEY && val != EV_SW) { +- dev_err(&client->dev, +- "Invalid %s input type: %u\n", +- fwnode_get_name(chan_node), val); +- return -EINVAL; +- } +- +- iqs7222->kp_type[chan_index][i] = val; +- } +- +- /* +- * Reference channels can opt out of event reporting by using +- * KEY_RESERVED in place of a true key or switch code. +- */ +- if (iqs7222->kp_type[chan_index][i] == EV_KEY && +- iqs7222->kp_code[chan_index][i] == KEY_RESERVED) +- continue; +- +- input_set_capability(iqs7222->keypad, +- iqs7222->kp_type[chan_index][i], +- iqs7222->kp_code[chan_index][i]); ++ error = iqs7222_parse_event(iqs7222, event_node, chan_index, ++ IQS7222_REG_GRP_BTN, ++ iqs7222_kp_events[i].reg_key, ++ BIT(chan_index), ++ dev_desc->touch_link - (i ? 0 : 2), ++ &iqs7222->kp_type[chan_index][i], ++ &iqs7222->kp_code[chan_index][i]); ++ fwnode_handle_put(event_node); ++ if (error) ++ return error; + + if (!dev_desc->event_offset) + continue; +@@ -1981,16 +2048,16 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index) + * The following call handles a special pair of properties that apply + * to a channel node, but reside within the button (event) group. + */ +- return iqs7222_parse_props(iqs7222, &chan_node, chan_index, ++ return iqs7222_parse_props(iqs7222, chan_node, chan_index, + IQS7222_REG_GRP_BTN, + IQS7222_REG_KEY_DEBOUNCE); + } + +-static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) ++static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, ++ struct fwnode_handle *sldr_node, int sldr_index) + { + const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc; + struct i2c_client *client = iqs7222->client; +- struct fwnode_handle *sldr_node = NULL; + int num_chan = dev_desc->reg_grps[IQS7222_REG_GRP_CHAN].num_row; + int ext_chan = rounddown(num_chan, 10); + int count, error, reg_offset, i; +@@ -1998,15 +2065,6 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) + u16 *sldr_setup = iqs7222->sldr_setup[sldr_index]; + unsigned int chan_sel[4], val; + +- error = iqs7222_parse_props(iqs7222, &sldr_node, sldr_index, +- IQS7222_REG_GRP_SLDR, +- IQS7222_REG_KEY_NONE); +- if (error) +- return error; +- +- if (!sldr_node) +- return 0; +- + /* + * Each slider can be spread across 3 to 4 channels. It is possible to + * select only 2 channels, but doing so prevents the slider from using +@@ -2065,8 +2123,9 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) + if (fwnode_property_present(sldr_node, "azoteq,use-prox")) + sldr_setup[4 + reg_offset] -= 2; + +- if (!fwnode_property_read_u32(sldr_node, "azoteq,slider-size", &val)) { +- if (!val || val > dev_desc->sldr_res) { ++ error = fwnode_property_read_u32(sldr_node, "azoteq,slider-size", &val); ++ if (!error) { ++ if (val > dev_desc->sldr_res) { + dev_err(&client->dev, "Invalid %s size: %u\n", + fwnode_get_name(sldr_node), val); + return -EINVAL; +@@ -2079,9 +2138,21 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) + sldr_setup[2] |= (val / 16 << + IQS7222_SLDR_SETUP_2_RES_SHIFT); + } ++ } else if (error != -EINVAL) { ++ dev_err(&client->dev, "Failed to read %s size: %d\n", ++ fwnode_get_name(sldr_node), error); ++ return error; + } + +- if (!fwnode_property_read_u32(sldr_node, "azoteq,top-speed", &val)) { ++ if (!(reg_offset ? sldr_setup[3] ++ : sldr_setup[2] & IQS7222_SLDR_SETUP_2_RES_MASK)) { ++ dev_err(&client->dev, "Undefined %s size\n", ++ fwnode_get_name(sldr_node)); ++ return -EINVAL; ++ } ++ ++ error = fwnode_property_read_u32(sldr_node, "azoteq,top-speed", &val); ++ if (!error) { + if (val > (reg_offset ? U16_MAX : U8_MAX * 4)) { + dev_err(&client->dev, "Invalid %s top speed: %u\n", + fwnode_get_name(sldr_node), val); +@@ -2094,9 +2165,14 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) + sldr_setup[2] &= ~IQS7222_SLDR_SETUP_2_TOP_SPEED_MASK; + sldr_setup[2] |= (val / 4); + } ++ } else if (error != -EINVAL) { ++ dev_err(&client->dev, "Failed to read %s top speed: %d\n", ++ fwnode_get_name(sldr_node), error); ++ return error; + } + +- if (!fwnode_property_read_u32(sldr_node, "linux,axis", &val)) { ++ error = fwnode_property_read_u32(sldr_node, "linux,axis", &val); ++ if (!error) { + u16 sldr_max = sldr_setup[3] - 1; + + if (!reg_offset) { +@@ -2110,6 +2186,10 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) + + input_set_abs_params(iqs7222->keypad, val, 0, sldr_max, 0, 0); + iqs7222->sl_axis[sldr_index] = val; ++ } else if (error != -EINVAL) { ++ dev_err(&client->dev, "Failed to read %s axis: %d\n", ++ fwnode_get_name(sldr_node), error); ++ return error; + } + + if (dev_desc->wheel_enable) { +@@ -2130,46 +2210,47 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) + for (i = 0; i < ARRAY_SIZE(iqs7222_sl_events); i++) { + const char *event_name = iqs7222_sl_events[i].name; + struct fwnode_handle *event_node; ++ enum iqs7222_reg_key_id reg_key; + + event_node = fwnode_get_named_child_node(sldr_node, event_name); + if (!event_node) + continue; + +- error = iqs7222_parse_props(iqs7222, &event_node, sldr_index, +- IQS7222_REG_GRP_SLDR, +- reg_offset ? +- IQS7222_REG_KEY_RESERVED : +- iqs7222_sl_events[i].reg_key); +- if (error) +- return error; ++ /* ++ * Depending on the device, gestures are either offered using ++ * one of two timing resolutions, or are not supported at all. ++ */ ++ if (reg_offset) ++ reg_key = IQS7222_REG_KEY_RESERVED; ++ else if (dev_desc->legacy_gesture && ++ iqs7222_sl_events[i].reg_key == IQS7222_REG_KEY_TAP) ++ reg_key = IQS7222_REG_KEY_TAP_LEGACY; ++ else if (dev_desc->legacy_gesture && ++ iqs7222_sl_events[i].reg_key == IQS7222_REG_KEY_AXIAL) ++ reg_key = IQS7222_REG_KEY_AXIAL_LEGACY; ++ else ++ reg_key = iqs7222_sl_events[i].reg_key; + + /* + * The press/release event does not expose a direct GPIO link, + * but one can be emulated by tying each of the participating + * channels to the same GPIO. + */ +- error = iqs7222_gpio_select(iqs7222, event_node, ++ error = iqs7222_parse_event(iqs7222, event_node, sldr_index, ++ IQS7222_REG_GRP_SLDR, reg_key, + i ? iqs7222_sl_events[i].enable + : sldr_setup[3 + reg_offset], + i ? 1568 + sldr_index * 30 +- : sldr_setup[4 + reg_offset]); ++ : sldr_setup[4 + reg_offset], ++ NULL, ++ &iqs7222->sl_code[sldr_index][i]); ++ fwnode_handle_put(event_node); + if (error) + return error; + + if (!reg_offset) + sldr_setup[9] |= iqs7222_sl_events[i].enable; + +- error = fwnode_property_read_u32(event_node, "linux,code", +- &val); +- if (error) { +- dev_err(&client->dev, "Failed to read %s code: %d\n", +- fwnode_get_name(sldr_node), error); +- return error; +- } +- +- iqs7222->sl_code[sldr_index][i] = val; +- input_set_capability(iqs7222->keypad, EV_KEY, val); +- + if (!dev_desc->event_offset) + continue; + +@@ -2190,19 +2271,63 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) + * The following call handles a special pair of properties that shift + * to make room for a wheel enable control in the case of IQS7222C. + */ +- return iqs7222_parse_props(iqs7222, &sldr_node, sldr_index, ++ return iqs7222_parse_props(iqs7222, sldr_node, sldr_index, + IQS7222_REG_GRP_SLDR, + dev_desc->wheel_enable ? + IQS7222_REG_KEY_WHEEL : + IQS7222_REG_KEY_NO_WHEEL); + } + ++static int (*iqs7222_parse_extra[IQS7222_NUM_REG_GRPS]) ++ (struct iqs7222_private *iqs7222, ++ struct fwnode_handle *reg_grp_node, ++ int reg_grp_index) = { ++ [IQS7222_REG_GRP_CYCLE] = iqs7222_parse_cycle, ++ [IQS7222_REG_GRP_CHAN] = iqs7222_parse_chan, ++ [IQS7222_REG_GRP_SLDR] = iqs7222_parse_sldr, ++}; ++ ++static int iqs7222_parse_reg_grp(struct iqs7222_private *iqs7222, ++ enum iqs7222_reg_grp_id reg_grp, ++ int reg_grp_index) ++{ ++ struct i2c_client *client = iqs7222->client; ++ struct fwnode_handle *reg_grp_node; ++ int error; ++ ++ if (iqs7222_reg_grp_names[reg_grp]) { ++ char reg_grp_name[16]; ++ ++ snprintf(reg_grp_name, sizeof(reg_grp_name), "%s-%d", ++ iqs7222_reg_grp_names[reg_grp], reg_grp_index); ++ ++ reg_grp_node = device_get_named_child_node(&client->dev, ++ reg_grp_name); ++ } else { ++ reg_grp_node = fwnode_handle_get(dev_fwnode(&client->dev)); ++ } ++ ++ if (!reg_grp_node) ++ return 0; ++ ++ error = iqs7222_parse_props(iqs7222, reg_grp_node, reg_grp_index, ++ reg_grp, IQS7222_REG_KEY_NONE); ++ ++ if (!error && iqs7222_parse_extra[reg_grp]) ++ error = iqs7222_parse_extra[reg_grp](iqs7222, reg_grp_node, ++ reg_grp_index); ++ ++ fwnode_handle_put(reg_grp_node); ++ ++ return error; ++} ++ + static int iqs7222_parse_all(struct iqs7222_private *iqs7222) + { + const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc; + const struct iqs7222_reg_grp_desc *reg_grps = dev_desc->reg_grps; + u16 *sys_setup = iqs7222->sys_setup; +- int error, i; ++ int error, i, j; + + if (dev_desc->allow_offset) + sys_setup[dev_desc->allow_offset] = U16_MAX; +@@ -2210,32 +2335,13 @@ static int iqs7222_parse_all(struct iqs7222_private *iqs7222) + if (dev_desc->event_offset) + sys_setup[dev_desc->event_offset] = IQS7222_EVENT_MASK_ATI; + +- for (i = 0; i < reg_grps[IQS7222_REG_GRP_CYCLE].num_row; i++) { +- error = iqs7222_parse_cycle(iqs7222, i); +- if (error) +- return error; +- } +- +- error = iqs7222_parse_props(iqs7222, NULL, 0, IQS7222_REG_GRP_GLBL, +- IQS7222_REG_KEY_NONE); +- if (error) +- return error; +- + for (i = 0; i < reg_grps[IQS7222_REG_GRP_GPIO].num_row; i++) { +- struct fwnode_handle *gpio_node = NULL; + u16 *gpio_setup = iqs7222->gpio_setup[i]; +- int j; + + gpio_setup[0] &= ~IQS7222_GPIO_SETUP_0_GPIO_EN; + gpio_setup[1] = 0; + gpio_setup[2] = 0; + +- error = iqs7222_parse_props(iqs7222, &gpio_node, i, +- IQS7222_REG_GRP_GPIO, +- IQS7222_REG_KEY_NONE); +- if (error) +- return error; +- + if (reg_grps[IQS7222_REG_GRP_GPIO].num_row == 1) + continue; + +@@ -2258,29 +2364,21 @@ static int iqs7222_parse_all(struct iqs7222_private *iqs7222) + chan_setup[5] = 0; + } + +- for (i = 0; i < reg_grps[IQS7222_REG_GRP_CHAN].num_row; i++) { +- error = iqs7222_parse_chan(iqs7222, i); +- if (error) +- return error; +- } +- +- error = iqs7222_parse_props(iqs7222, NULL, 0, IQS7222_REG_GRP_FILT, +- IQS7222_REG_KEY_NONE); +- if (error) +- return error; +- + for (i = 0; i < reg_grps[IQS7222_REG_GRP_SLDR].num_row; i++) { + u16 *sldr_setup = iqs7222->sldr_setup[i]; + + sldr_setup[0] &= ~IQS7222_SLDR_SETUP_0_CHAN_CNT_MASK; ++ } + +- error = iqs7222_parse_sldr(iqs7222, i); +- if (error) +- return error; ++ for (i = 0; i < IQS7222_NUM_REG_GRPS; i++) { ++ for (j = 0; j < reg_grps[i].num_row; j++) { ++ error = iqs7222_parse_reg_grp(iqs7222, i, j); ++ if (error) ++ return error; ++ } + } + +- return iqs7222_parse_props(iqs7222, NULL, 0, IQS7222_REG_GRP_SYS, +- IQS7222_REG_KEY_NONE); ++ return 0; + } + + static int iqs7222_report(struct iqs7222_private *iqs7222) +diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c +index 879a4d984c907..e1308e179dd6f 100644 +--- a/drivers/input/touchscreen/elants_i2c.c ++++ b/drivers/input/touchscreen/elants_i2c.c +@@ -1329,14 +1329,12 @@ static int elants_i2c_power_on(struct elants_data *ts) + if (IS_ERR_OR_NULL(ts->reset_gpio)) + return 0; + +- gpiod_set_value_cansleep(ts->reset_gpio, 1); +- + error = regulator_enable(ts->vcc33); + if (error) { + dev_err(&ts->client->dev, + "failed to enable vcc33 regulator: %d\n", + error); +- goto release_reset_gpio; ++ return error; + } + + error = regulator_enable(ts->vccio); +@@ -1345,7 +1343,7 @@ static int elants_i2c_power_on(struct elants_data *ts) + "failed to enable vccio regulator: %d\n", + error); + regulator_disable(ts->vcc33); +- goto release_reset_gpio; ++ return error; + } + + /* +@@ -1354,7 +1352,6 @@ static int elants_i2c_power_on(struct elants_data *ts) + */ + udelay(ELAN_POWERON_DELAY_USEC); + +-release_reset_gpio: + gpiod_set_value_cansleep(ts->reset_gpio, 0); + if (error) + return error; +@@ -1462,7 +1459,7 @@ static int elants_i2c_probe(struct i2c_client *client) + return error; + } + +- ts->reset_gpio = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_LOW); ++ ts->reset_gpio = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(ts->reset_gpio)) { + error = PTR_ERR(ts->reset_gpio); + +diff --git a/drivers/interconnect/qcom/sc7180.c b/drivers/interconnect/qcom/sc7180.c +index 35cd448efdfbe..82d5e8a8c19ea 100644 +--- a/drivers/interconnect/qcom/sc7180.c ++++ b/drivers/interconnect/qcom/sc7180.c +@@ -369,7 +369,7 @@ static const struct qcom_icc_desc sc7180_gem_noc = { + .num_bcms = ARRAY_SIZE(gem_noc_bcms), + }; + +-static struct qcom_icc_bcm *mc_virt_bcms[] = { ++static struct qcom_icc_bcm * const mc_virt_bcms[] = { + &bcm_acv, + &bcm_mc0, + }; +diff --git a/drivers/iommu/amd/iommu_v2.c b/drivers/iommu/amd/iommu_v2.c +index 6a1f02c62dffc..9f7fab49a5a90 100644 +--- a/drivers/iommu/amd/iommu_v2.c ++++ b/drivers/iommu/amd/iommu_v2.c +@@ -587,6 +587,7 @@ out_drop_state: + put_device_state(dev_state); + + out: ++ pci_dev_put(pdev); + return ret; + } + +diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c +index 0d03f837a5d4e..7a1a413f75ab2 100644 +--- a/drivers/iommu/fsl_pamu.c ++++ b/drivers/iommu/fsl_pamu.c +@@ -868,7 +868,7 @@ static int fsl_pamu_probe(struct platform_device *pdev) + ret = create_csd(ppaact_phys, mem_size, csd_port_id); + if (ret) { + dev_err(dev, "could not create coherence subdomain\n"); +- return ret; ++ goto error; + } + } + +diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c +index 65a3b3d886dc0..959d895fc1dff 100644 +--- a/drivers/iommu/iommu.c ++++ b/drivers/iommu/iommu.c +@@ -283,13 +283,23 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list + const struct iommu_ops *ops = dev->bus->iommu_ops; + struct iommu_device *iommu_dev; + struct iommu_group *group; ++ static DEFINE_MUTEX(iommu_probe_device_lock); + int ret; + + if (!ops) + return -ENODEV; +- +- if (!dev_iommu_get(dev)) +- return -ENOMEM; ++ /* ++ * Serialise to avoid races between IOMMU drivers registering in ++ * parallel and/or the "replay" calls from ACPI/OF code via client ++ * driver probe. Once the latter have been cleaned up we should ++ * probably be able to use device_lock() here to minimise the scope, ++ * but for now enforcing a simple global ordering is fine. ++ */ ++ mutex_lock(&iommu_probe_device_lock); ++ if (!dev_iommu_get(dev)) { ++ ret = -ENOMEM; ++ goto err_unlock; ++ } + + if (!try_module_get(ops->owner)) { + ret = -EINVAL; +@@ -309,11 +319,14 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list + ret = PTR_ERR(group); + goto out_release; + } +- iommu_group_put(group); + ++ mutex_lock(&group->mutex); + if (group_list && !group->default_domain && list_empty(&group->entry)) + list_add_tail(&group->entry, group_list); ++ mutex_unlock(&group->mutex); ++ iommu_group_put(group); + ++ mutex_unlock(&iommu_probe_device_lock); + iommu_device_link(iommu_dev, dev); + + return 0; +@@ -328,6 +341,9 @@ out_module_put: + err_free: + dev_iommu_free(dev); + ++err_unlock: ++ mutex_unlock(&iommu_probe_device_lock); ++ + return ret; + } + +@@ -1799,11 +1815,11 @@ int bus_iommu_probe(struct bus_type *bus) + return ret; + + list_for_each_entry_safe(group, next, &group_list, entry) { ++ mutex_lock(&group->mutex); ++ + /* Remove item from the list */ + list_del_init(&group->entry); + +- mutex_lock(&group->mutex); +- + /* Try to allocate default domain */ + probe_alloc_default_domain(bus, group); + +diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c +index 2ab2ecfe01f80..56d007582b6fa 100644 +--- a/drivers/iommu/mtk_iommu.c ++++ b/drivers/iommu/mtk_iommu.c +@@ -454,7 +454,7 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) + fault_larb = data->plat_data->larbid_remap[fault_larb][sub_comm]; + } + +- if (report_iommu_fault(&dom->domain, bank->parent_dev, fault_iova, ++ if (!dom || report_iommu_fault(&dom->domain, bank->parent_dev, fault_iova, + write ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ)) { + dev_err_ratelimited( + bank->parent_dev, +@@ -1044,20 +1044,24 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m + struct mtk_iommu_data *data) + { + struct device_node *larbnode, *smicomm_node, *smi_subcomm_node; +- struct platform_device *plarbdev; ++ struct platform_device *plarbdev, *pcommdev; + struct device_link *link; + int i, larb_nr, ret; + + larb_nr = of_count_phandle_with_args(dev->of_node, "mediatek,larbs", NULL); + if (larb_nr < 0) + return larb_nr; ++ if (larb_nr == 0 || larb_nr > MTK_LARB_NR_MAX) ++ return -EINVAL; + + for (i = 0; i < larb_nr; i++) { + u32 id; + + larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i); +- if (!larbnode) +- return -EINVAL; ++ if (!larbnode) { ++ ret = -EINVAL; ++ goto err_larbdev_put; ++ } + + if (!of_device_is_available(larbnode)) { + of_node_put(larbnode); +@@ -1067,20 +1071,32 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m + ret = of_property_read_u32(larbnode, "mediatek,larb-id", &id); + if (ret)/* The id is consecutive if there is no this property */ + id = i; ++ if (id >= MTK_LARB_NR_MAX) { ++ of_node_put(larbnode); ++ ret = -EINVAL; ++ goto err_larbdev_put; ++ } + + plarbdev = of_find_device_by_node(larbnode); ++ of_node_put(larbnode); + if (!plarbdev) { +- of_node_put(larbnode); +- return -ENODEV; ++ ret = -ENODEV; ++ goto err_larbdev_put; + } +- if (!plarbdev->dev.driver) { +- of_node_put(larbnode); +- return -EPROBE_DEFER; ++ if (data->larb_imu[id].dev) { ++ platform_device_put(plarbdev); ++ ret = -EEXIST; ++ goto err_larbdev_put; + } + data->larb_imu[id].dev = &plarbdev->dev; + +- component_match_add_release(dev, match, component_release_of, +- component_compare_of, larbnode); ++ if (!plarbdev->dev.driver) { ++ ret = -EPROBE_DEFER; ++ goto err_larbdev_put; ++ } ++ ++ component_match_add(dev, match, component_compare_dev, &plarbdev->dev); ++ platform_device_put(plarbdev); + } + + /* Get smi-(sub)-common dev from the last larb. */ +@@ -1098,17 +1114,28 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m + else + smicomm_node = smi_subcomm_node; + +- plarbdev = of_find_device_by_node(smicomm_node); ++ pcommdev = of_find_device_by_node(smicomm_node); + of_node_put(smicomm_node); +- data->smicomm_dev = &plarbdev->dev; ++ if (!pcommdev) ++ return -ENODEV; ++ data->smicomm_dev = &pcommdev->dev; + + link = device_link_add(data->smicomm_dev, dev, + DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME); ++ platform_device_put(pcommdev); + if (!link) { + dev_err(dev, "Unable to link %s.\n", dev_name(data->smicomm_dev)); + return -EINVAL; + } + return 0; ++ ++err_larbdev_put: ++ for (i = MTK_LARB_NR_MAX - 1; i >= 0; i--) { ++ if (!data->larb_imu[i].dev) ++ continue; ++ put_device(data->larb_imu[i].dev); ++ } ++ return ret; + } + + static int mtk_iommu_probe(struct platform_device *pdev) +@@ -1173,6 +1200,8 @@ static int mtk_iommu_probe(struct platform_device *pdev) + + banks_num = data->plat_data->banks_num; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) ++ return -EINVAL; + if (resource_size(res) < banks_num * MTK_IOMMU_BANK_SZ) { + dev_err(dev, "banknr %d. res %pR is not enough.\n", banks_num, res); + return -EINVAL; +diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c +index a3fc59b814ab5..a68eadd64f38d 100644 +--- a/drivers/iommu/rockchip-iommu.c ++++ b/drivers/iommu/rockchip-iommu.c +@@ -280,19 +280,17 @@ static u32 rk_mk_pte(phys_addr_t page, int prot) + * 11:9 - Page address bit 34:32 + * 8:4 - Page address bit 39:35 + * 3 - Security +- * 2 - Readable +- * 1 - Writable ++ * 2 - Writable ++ * 1 - Readable + * 0 - 1 if Page @ Page address is valid + */ +-#define RK_PTE_PAGE_READABLE_V2 BIT(2) +-#define RK_PTE_PAGE_WRITABLE_V2 BIT(1) + + static u32 rk_mk_pte_v2(phys_addr_t page, int prot) + { + u32 flags = 0; + +- flags |= (prot & IOMMU_READ) ? RK_PTE_PAGE_READABLE_V2 : 0; +- flags |= (prot & IOMMU_WRITE) ? RK_PTE_PAGE_WRITABLE_V2 : 0; ++ flags |= (prot & IOMMU_READ) ? RK_PTE_PAGE_READABLE : 0; ++ flags |= (prot & IOMMU_WRITE) ? RK_PTE_PAGE_WRITABLE : 0; + + return rk_mk_dte_v2(page) | flags; + } +diff --git a/drivers/iommu/s390-iommu.c b/drivers/iommu/s390-iommu.c +index 3c071782f6f16..c2e5e81d609e1 100644 +--- a/drivers/iommu/s390-iommu.c ++++ b/drivers/iommu/s390-iommu.c +@@ -79,10 +79,36 @@ static void s390_domain_free(struct iommu_domain *domain) + { + struct s390_domain *s390_domain = to_s390_domain(domain); + ++ WARN_ON(!list_empty(&s390_domain->devices)); + dma_cleanup_tables(s390_domain->dma_table); + kfree(s390_domain); + } + ++static void __s390_iommu_detach_device(struct zpci_dev *zdev) ++{ ++ struct s390_domain *s390_domain = zdev->s390_domain; ++ struct s390_domain_device *domain_device, *tmp; ++ unsigned long flags; ++ ++ if (!s390_domain) ++ return; ++ ++ spin_lock_irqsave(&s390_domain->list_lock, flags); ++ list_for_each_entry_safe(domain_device, tmp, &s390_domain->devices, ++ list) { ++ if (domain_device->zdev == zdev) { ++ list_del(&domain_device->list); ++ kfree(domain_device); ++ break; ++ } ++ } ++ spin_unlock_irqrestore(&s390_domain->list_lock, flags); ++ ++ zpci_unregister_ioat(zdev, 0); ++ zdev->s390_domain = NULL; ++ zdev->dma_table = NULL; ++} ++ + static int s390_iommu_attach_device(struct iommu_domain *domain, + struct device *dev) + { +@@ -90,7 +116,7 @@ static int s390_iommu_attach_device(struct iommu_domain *domain, + struct zpci_dev *zdev = to_zpci_dev(dev); + struct s390_domain_device *domain_device; + unsigned long flags; +- int cc, rc; ++ int cc, rc = 0; + + if (!zdev) + return -ENODEV; +@@ -99,24 +125,18 @@ static int s390_iommu_attach_device(struct iommu_domain *domain, + if (!domain_device) + return -ENOMEM; + +- if (zdev->dma_table && !zdev->s390_domain) { +- cc = zpci_dma_exit_device(zdev); +- if (cc) { +- rc = -EIO; +- goto out_free; +- } +- } +- + if (zdev->s390_domain) +- zpci_unregister_ioat(zdev, 0); ++ __s390_iommu_detach_device(zdev); ++ else if (zdev->dma_table) ++ zpci_dma_exit_device(zdev); + +- zdev->dma_table = s390_domain->dma_table; + cc = zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma, +- virt_to_phys(zdev->dma_table)); ++ virt_to_phys(s390_domain->dma_table)); + if (cc) { + rc = -EIO; +- goto out_restore; ++ goto out_free; + } ++ zdev->dma_table = s390_domain->dma_table; + + spin_lock_irqsave(&s390_domain->list_lock, flags); + /* First device defines the DMA range limits */ +@@ -127,9 +147,9 @@ static int s390_iommu_attach_device(struct iommu_domain *domain, + /* Allow only devices with identical DMA range limits */ + } else if (domain->geometry.aperture_start != zdev->start_dma || + domain->geometry.aperture_end != zdev->end_dma) { +- rc = -EINVAL; + spin_unlock_irqrestore(&s390_domain->list_lock, flags); +- goto out_restore; ++ rc = -EINVAL; ++ goto out_unregister; + } + domain_device->zdev = zdev; + zdev->s390_domain = s390_domain; +@@ -138,14 +158,9 @@ static int s390_iommu_attach_device(struct iommu_domain *domain, + + return 0; + +-out_restore: +- if (!zdev->s390_domain) { +- zpci_dma_init_device(zdev); +- } else { +- zdev->dma_table = zdev->s390_domain->dma_table; +- zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma, +- virt_to_phys(zdev->dma_table)); +- } ++out_unregister: ++ zpci_unregister_ioat(zdev, 0); ++ zdev->dma_table = NULL; + out_free: + kfree(domain_device); + +@@ -155,32 +170,12 @@ out_free: + static void s390_iommu_detach_device(struct iommu_domain *domain, + struct device *dev) + { +- struct s390_domain *s390_domain = to_s390_domain(domain); + struct zpci_dev *zdev = to_zpci_dev(dev); +- struct s390_domain_device *domain_device, *tmp; +- unsigned long flags; +- int found = 0; + +- if (!zdev) +- return; ++ WARN_ON(zdev->s390_domain != to_s390_domain(domain)); + +- spin_lock_irqsave(&s390_domain->list_lock, flags); +- list_for_each_entry_safe(domain_device, tmp, &s390_domain->devices, +- list) { +- if (domain_device->zdev == zdev) { +- list_del(&domain_device->list); +- kfree(domain_device); +- found = 1; +- break; +- } +- } +- spin_unlock_irqrestore(&s390_domain->list_lock, flags); +- +- if (found && (zdev->s390_domain == s390_domain)) { +- zdev->s390_domain = NULL; +- zpci_unregister_ioat(zdev, 0); +- zpci_dma_init_device(zdev); +- } ++ __s390_iommu_detach_device(zdev); ++ zpci_dma_init_device(zdev); + } + + static struct iommu_device *s390_iommu_probe_device(struct device *dev) +@@ -198,24 +193,13 @@ static struct iommu_device *s390_iommu_probe_device(struct device *dev) + static void s390_iommu_release_device(struct device *dev) + { + struct zpci_dev *zdev = to_zpci_dev(dev); +- struct iommu_domain *domain; + + /* +- * This is a workaround for a scenario where the IOMMU API common code +- * "forgets" to call the detach_dev callback: After binding a device +- * to vfio-pci and completing the VFIO_SET_IOMMU ioctl (which triggers +- * the attach_dev), removing the device via +- * "echo 1 > /sys/bus/pci/devices/.../remove" won't trigger detach_dev, +- * only release_device will be called via the BUS_NOTIFY_REMOVED_DEVICE +- * notifier. +- * +- * So let's call detach_dev from here if it hasn't been called before. ++ * release_device is expected to detach any domain currently attached ++ * to the device, but keep it attached to other devices in the group. + */ +- if (zdev && zdev->s390_domain) { +- domain = iommu_get_domain_for_dev(dev); +- if (domain) +- s390_iommu_detach_device(domain, dev); +- } ++ if (zdev) ++ __s390_iommu_detach_device(zdev); + } + + static int s390_iommu_update_trans(struct s390_domain *s390_domain, +diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c +index cd9b74ee24def..5b585eace3d46 100644 +--- a/drivers/iommu/sun50i-iommu.c ++++ b/drivers/iommu/sun50i-iommu.c +@@ -27,6 +27,7 @@ + #include <linux/types.h> + + #define IOMMU_RESET_REG 0x010 ++#define IOMMU_RESET_RELEASE_ALL 0xffffffff + #define IOMMU_ENABLE_REG 0x020 + #define IOMMU_ENABLE_ENABLE BIT(0) + +@@ -92,6 +93,8 @@ + #define NUM_PT_ENTRIES 256 + #define PT_SIZE (NUM_PT_ENTRIES * PT_ENTRY_SIZE) + ++#define SPAGE_SIZE 4096 ++ + struct sun50i_iommu { + struct iommu_device iommu; + +@@ -270,7 +273,7 @@ static u32 sun50i_mk_pte(phys_addr_t page, int prot) + enum sun50i_iommu_aci aci; + u32 flags = 0; + +- if (prot & (IOMMU_READ | IOMMU_WRITE)) ++ if ((prot & (IOMMU_READ | IOMMU_WRITE)) == (IOMMU_READ | IOMMU_WRITE)) + aci = SUN50I_IOMMU_ACI_RD_WR; + else if (prot & IOMMU_READ) + aci = SUN50I_IOMMU_ACI_RD; +@@ -294,6 +297,62 @@ static void sun50i_table_flush(struct sun50i_iommu_domain *sun50i_domain, + dma_sync_single_for_device(iommu->dev, dma, size, DMA_TO_DEVICE); + } + ++static void sun50i_iommu_zap_iova(struct sun50i_iommu *iommu, ++ unsigned long iova) ++{ ++ u32 reg; ++ int ret; ++ ++ iommu_write(iommu, IOMMU_TLB_IVLD_ADDR_REG, iova); ++ iommu_write(iommu, IOMMU_TLB_IVLD_ADDR_MASK_REG, GENMASK(31, 12)); ++ iommu_write(iommu, IOMMU_TLB_IVLD_ENABLE_REG, ++ IOMMU_TLB_IVLD_ENABLE_ENABLE); ++ ++ ret = readl_poll_timeout_atomic(iommu->base + IOMMU_TLB_IVLD_ENABLE_REG, ++ reg, !reg, 1, 2000); ++ if (ret) ++ dev_warn(iommu->dev, "TLB invalidation timed out!\n"); ++} ++ ++static void sun50i_iommu_zap_ptw_cache(struct sun50i_iommu *iommu, ++ unsigned long iova) ++{ ++ u32 reg; ++ int ret; ++ ++ iommu_write(iommu, IOMMU_PC_IVLD_ADDR_REG, iova); ++ iommu_write(iommu, IOMMU_PC_IVLD_ENABLE_REG, ++ IOMMU_PC_IVLD_ENABLE_ENABLE); ++ ++ ret = readl_poll_timeout_atomic(iommu->base + IOMMU_PC_IVLD_ENABLE_REG, ++ reg, !reg, 1, 2000); ++ if (ret) ++ dev_warn(iommu->dev, "PTW cache invalidation timed out!\n"); ++} ++ ++static void sun50i_iommu_zap_range(struct sun50i_iommu *iommu, ++ unsigned long iova, size_t size) ++{ ++ assert_spin_locked(&iommu->iommu_lock); ++ ++ iommu_write(iommu, IOMMU_AUTO_GATING_REG, 0); ++ ++ sun50i_iommu_zap_iova(iommu, iova); ++ sun50i_iommu_zap_iova(iommu, iova + SPAGE_SIZE); ++ if (size > SPAGE_SIZE) { ++ sun50i_iommu_zap_iova(iommu, iova + size); ++ sun50i_iommu_zap_iova(iommu, iova + size + SPAGE_SIZE); ++ } ++ sun50i_iommu_zap_ptw_cache(iommu, iova); ++ sun50i_iommu_zap_ptw_cache(iommu, iova + SZ_1M); ++ if (size > SZ_1M) { ++ sun50i_iommu_zap_ptw_cache(iommu, iova + size); ++ sun50i_iommu_zap_ptw_cache(iommu, iova + size + SZ_1M); ++ } ++ ++ iommu_write(iommu, IOMMU_AUTO_GATING_REG, IOMMU_AUTO_GATING_ENABLE); ++} ++ + static int sun50i_iommu_flush_all_tlb(struct sun50i_iommu *iommu) + { + u32 reg; +@@ -343,6 +402,18 @@ static void sun50i_iommu_flush_iotlb_all(struct iommu_domain *domain) + spin_unlock_irqrestore(&iommu->iommu_lock, flags); + } + ++static void sun50i_iommu_iotlb_sync_map(struct iommu_domain *domain, ++ unsigned long iova, size_t size) ++{ ++ struct sun50i_iommu_domain *sun50i_domain = to_sun50i_domain(domain); ++ struct sun50i_iommu *iommu = sun50i_domain->iommu; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&iommu->iommu_lock, flags); ++ sun50i_iommu_zap_range(iommu, iova, size); ++ spin_unlock_irqrestore(&iommu->iommu_lock, flags); ++} ++ + static void sun50i_iommu_iotlb_sync(struct iommu_domain *domain, + struct iommu_iotlb_gather *gather) + { +@@ -511,7 +582,7 @@ static u32 *sun50i_dte_get_page_table(struct sun50i_iommu_domain *sun50i_domain, + sun50i_iommu_free_page_table(iommu, drop_pt); + } + +- sun50i_table_flush(sun50i_domain, page_table, PT_SIZE); ++ sun50i_table_flush(sun50i_domain, page_table, NUM_PT_ENTRIES); + sun50i_table_flush(sun50i_domain, dte_addr, 1); + + return page_table; +@@ -601,7 +672,6 @@ static struct iommu_domain *sun50i_iommu_domain_alloc(unsigned type) + struct sun50i_iommu_domain *sun50i_domain; + + if (type != IOMMU_DOMAIN_DMA && +- type != IOMMU_DOMAIN_IDENTITY && + type != IOMMU_DOMAIN_UNMANAGED) + return NULL; + +@@ -766,6 +836,7 @@ static const struct iommu_ops sun50i_iommu_ops = { + .attach_dev = sun50i_iommu_attach_device, + .detach_dev = sun50i_iommu_detach_device, + .flush_iotlb_all = sun50i_iommu_flush_iotlb_all, ++ .iotlb_sync_map = sun50i_iommu_iotlb_sync_map, + .iotlb_sync = sun50i_iommu_iotlb_sync, + .iova_to_phys = sun50i_iommu_iova_to_phys, + .map = sun50i_iommu_map, +@@ -785,6 +856,8 @@ static void sun50i_iommu_report_fault(struct sun50i_iommu *iommu, + report_iommu_fault(iommu->domain, iommu->dev, iova, prot); + else + dev_err(iommu->dev, "Page fault while iommu not attached to any domain?\n"); ++ ++ sun50i_iommu_zap_range(iommu, iova, SPAGE_SIZE); + } + + static phys_addr_t sun50i_iommu_handle_pt_irq(struct sun50i_iommu *iommu, +@@ -868,8 +941,8 @@ static phys_addr_t sun50i_iommu_handle_perm_irq(struct sun50i_iommu *iommu) + + static irqreturn_t sun50i_iommu_irq(int irq, void *dev_id) + { ++ u32 status, l1_status, l2_status, resets; + struct sun50i_iommu *iommu = dev_id; +- u32 status; + + spin_lock(&iommu->iommu_lock); + +@@ -879,6 +952,9 @@ static irqreturn_t sun50i_iommu_irq(int irq, void *dev_id) + return IRQ_NONE; + } + ++ l1_status = iommu_read(iommu, IOMMU_L1PG_INT_REG); ++ l2_status = iommu_read(iommu, IOMMU_L2PG_INT_REG); ++ + if (status & IOMMU_INT_INVALID_L2PG) + sun50i_iommu_handle_pt_irq(iommu, + IOMMU_INT_ERR_ADDR_L2_REG, +@@ -892,8 +968,9 @@ static irqreturn_t sun50i_iommu_irq(int irq, void *dev_id) + + iommu_write(iommu, IOMMU_INT_CLR_REG, status); + +- iommu_write(iommu, IOMMU_RESET_REG, ~status); +- iommu_write(iommu, IOMMU_RESET_REG, status); ++ resets = (status | l1_status | l2_status) & IOMMU_INT_MASTER_MASK; ++ iommu_write(iommu, IOMMU_RESET_REG, ~resets); ++ iommu_write(iommu, IOMMU_RESET_REG, IOMMU_RESET_RELEASE_ALL); + + spin_unlock(&iommu->iommu_lock); + +diff --git a/drivers/irqchip/irq-gic-pm.c b/drivers/irqchip/irq-gic-pm.c +index b60e1853593f4..3989d16f997b3 100644 +--- a/drivers/irqchip/irq-gic-pm.c ++++ b/drivers/irqchip/irq-gic-pm.c +@@ -102,7 +102,7 @@ static int gic_probe(struct platform_device *pdev) + + pm_runtime_enable(dev); + +- ret = pm_runtime_get_sync(dev); ++ ret = pm_runtime_resume_and_get(dev); + if (ret < 0) + goto rpm_disable; + +diff --git a/drivers/irqchip/irq-loongson-liointc.c b/drivers/irqchip/irq-loongson-liointc.c +index 0da8716f8f24b..c4584e2f0ad3d 100644 +--- a/drivers/irqchip/irq-loongson-liointc.c ++++ b/drivers/irqchip/irq-loongson-liointc.c +@@ -207,10 +207,13 @@ static int liointc_init(phys_addr_t addr, unsigned long size, int revision, + "reg-names", core_reg_names[i]); + + if (index < 0) +- goto out_iounmap; ++ continue; + + priv->core_isr[i] = of_iomap(node, index); + } ++ ++ if (!priv->core_isr[0]) ++ goto out_iounmap; + } + + /* Setup IRQ domain */ +diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c +index c01b9c2570053..03493cda65a37 100644 +--- a/drivers/irqchip/irq-loongson-pch-pic.c ++++ b/drivers/irqchip/irq-loongson-pch-pic.c +@@ -159,6 +159,9 @@ static int pch_pic_domain_translate(struct irq_domain *d, + return -EINVAL; + + if (of_node) { ++ if (fwspec->param_count < 2) ++ return -EINVAL; ++ + *hwirq = fwspec->param[0] + priv->ht_vec_base; + *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; + } else { +diff --git a/drivers/irqchip/irq-ls-extirq.c b/drivers/irqchip/irq-ls-extirq.c +index d8d48b1f7c29d..139f26b0a6ef8 100644 +--- a/drivers/irqchip/irq-ls-extirq.c ++++ b/drivers/irqchip/irq-ls-extirq.c +@@ -203,7 +203,7 @@ ls_extirq_of_init(struct device_node *node, struct device_node *parent) + if (ret) + goto err_parse_map; + +- priv->big_endian = of_device_is_big_endian(parent); ++ priv->big_endian = of_device_is_big_endian(node->parent); + priv->is_ls1021a_or_ls1043a = of_device_is_compatible(node, "fsl,ls1021a-extirq") || + of_device_is_compatible(node, "fsl,ls1043a-extirq"); + raw_spin_lock_init(&priv->lock); +diff --git a/drivers/irqchip/irq-wpcm450-aic.c b/drivers/irqchip/irq-wpcm450-aic.c +index 0dcbeb1a05a1f..91df62a64cd91 100644 +--- a/drivers/irqchip/irq-wpcm450-aic.c ++++ b/drivers/irqchip/irq-wpcm450-aic.c +@@ -146,6 +146,7 @@ static int __init wpcm450_aic_of_init(struct device_node *node, + aic->regs = of_iomap(node, 0); + if (!aic->regs) { + pr_err("Failed to map WPCM450 AIC registers\n"); ++ kfree(aic); + return -ENOMEM; + } + +diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c +index 4f7eaa17fb274..e840609c50eb7 100644 +--- a/drivers/isdn/hardware/mISDN/hfcmulti.c ++++ b/drivers/isdn/hardware/mISDN/hfcmulti.c +@@ -3217,6 +3217,7 @@ static int + hfcm_l1callback(struct dchannel *dch, u_int cmd) + { + struct hfc_multi *hc = dch->hw; ++ struct sk_buff_head free_queue; + u_long flags; + + switch (cmd) { +@@ -3245,6 +3246,7 @@ hfcm_l1callback(struct dchannel *dch, u_int cmd) + l1_event(dch->l1, HW_POWERUP_IND); + break; + case HW_DEACT_REQ: ++ __skb_queue_head_init(&free_queue); + /* start deactivation */ + spin_lock_irqsave(&hc->lock, flags); + if (hc->ctype == HFC_TYPE_E1) { +@@ -3264,20 +3266,21 @@ hfcm_l1callback(struct dchannel *dch, u_int cmd) + plxsd_checksync(hc, 0); + } + } +- skb_queue_purge(&dch->squeue); ++ skb_queue_splice_init(&dch->squeue, &free_queue); + if (dch->tx_skb) { +- dev_kfree_skb(dch->tx_skb); ++ __skb_queue_tail(&free_queue, dch->tx_skb); + dch->tx_skb = NULL; + } + dch->tx_idx = 0; + if (dch->rx_skb) { +- dev_kfree_skb(dch->rx_skb); ++ __skb_queue_tail(&free_queue, dch->rx_skb); + dch->rx_skb = NULL; + } + test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); + if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags)) + del_timer(&dch->timer); + spin_unlock_irqrestore(&hc->lock, flags); ++ __skb_queue_purge(&free_queue); + break; + case HW_POWERUP_REQ: + spin_lock_irqsave(&hc->lock, flags); +@@ -3384,6 +3387,9 @@ handle_dmsg(struct mISDNchannel *ch, struct sk_buff *skb) + case PH_DEACTIVATE_REQ: + test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags); + if (dch->dev.D.protocol != ISDN_P_TE_S0) { ++ struct sk_buff_head free_queue; ++ ++ __skb_queue_head_init(&free_queue); + spin_lock_irqsave(&hc->lock, flags); + if (debug & DEBUG_HFCMULTI_MSG) + printk(KERN_DEBUG +@@ -3405,14 +3411,14 @@ handle_dmsg(struct mISDNchannel *ch, struct sk_buff *skb) + /* deactivate */ + dch->state = 1; + } +- skb_queue_purge(&dch->squeue); ++ skb_queue_splice_init(&dch->squeue, &free_queue); + if (dch->tx_skb) { +- dev_kfree_skb(dch->tx_skb); ++ __skb_queue_tail(&free_queue, dch->tx_skb); + dch->tx_skb = NULL; + } + dch->tx_idx = 0; + if (dch->rx_skb) { +- dev_kfree_skb(dch->rx_skb); ++ __skb_queue_tail(&free_queue, dch->rx_skb); + dch->rx_skb = NULL; + } + test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); +@@ -3424,6 +3430,7 @@ handle_dmsg(struct mISDNchannel *ch, struct sk_buff *skb) + #endif + ret = 0; + spin_unlock_irqrestore(&hc->lock, flags); ++ __skb_queue_purge(&free_queue); + } else + ret = l1_event(dch->l1, hh->prim); + break; +diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c +index e964a8dd8512a..c0331b2680108 100644 +--- a/drivers/isdn/hardware/mISDN/hfcpci.c ++++ b/drivers/isdn/hardware/mISDN/hfcpci.c +@@ -1617,16 +1617,19 @@ hfcpci_l2l1D(struct mISDNchannel *ch, struct sk_buff *skb) + test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags); + spin_lock_irqsave(&hc->lock, flags); + if (hc->hw.protocol == ISDN_P_NT_S0) { ++ struct sk_buff_head free_queue; ++ ++ __skb_queue_head_init(&free_queue); + /* prepare deactivation */ + Write_hfc(hc, HFCPCI_STATES, 0x40); +- skb_queue_purge(&dch->squeue); ++ skb_queue_splice_init(&dch->squeue, &free_queue); + if (dch->tx_skb) { +- dev_kfree_skb(dch->tx_skb); ++ __skb_queue_tail(&free_queue, dch->tx_skb); + dch->tx_skb = NULL; + } + dch->tx_idx = 0; + if (dch->rx_skb) { +- dev_kfree_skb(dch->rx_skb); ++ __skb_queue_tail(&free_queue, dch->rx_skb); + dch->rx_skb = NULL; + } + test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); +@@ -1639,10 +1642,12 @@ hfcpci_l2l1D(struct mISDNchannel *ch, struct sk_buff *skb) + hc->hw.mst_m &= ~HFCPCI_MASTER; + Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m); + ret = 0; ++ spin_unlock_irqrestore(&hc->lock, flags); ++ __skb_queue_purge(&free_queue); + } else { + ret = l1_event(dch->l1, hh->prim); ++ spin_unlock_irqrestore(&hc->lock, flags); + } +- spin_unlock_irqrestore(&hc->lock, flags); + break; + } + if (!ret) +diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c +index 651f2f8f685b7..1efd17979f240 100644 +--- a/drivers/isdn/hardware/mISDN/hfcsusb.c ++++ b/drivers/isdn/hardware/mISDN/hfcsusb.c +@@ -326,20 +326,24 @@ hfcusb_l2l1D(struct mISDNchannel *ch, struct sk_buff *skb) + test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags); + + if (hw->protocol == ISDN_P_NT_S0) { ++ struct sk_buff_head free_queue; ++ ++ __skb_queue_head_init(&free_queue); + hfcsusb_ph_command(hw, HFC_L1_DEACTIVATE_NT); + spin_lock_irqsave(&hw->lock, flags); +- skb_queue_purge(&dch->squeue); ++ skb_queue_splice_init(&dch->squeue, &free_queue); + if (dch->tx_skb) { +- dev_kfree_skb(dch->tx_skb); ++ __skb_queue_tail(&free_queue, dch->tx_skb); + dch->tx_skb = NULL; + } + dch->tx_idx = 0; + if (dch->rx_skb) { +- dev_kfree_skb(dch->rx_skb); ++ __skb_queue_tail(&free_queue, dch->rx_skb); + dch->rx_skb = NULL; + } + test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); + spin_unlock_irqrestore(&hw->lock, flags); ++ __skb_queue_purge(&free_queue); + #ifdef FIXME + if (test_and_clear_bit(FLG_L1_BUSY, &dch->Flags)) + dchannel_sched_event(&hc->dch, D_CLEARBUSY); +@@ -1330,7 +1334,7 @@ tx_iso_complete(struct urb *urb) + printk("\n"); + } + +- dev_kfree_skb(tx_skb); ++ dev_consume_skb_irq(tx_skb); + tx_skb = NULL; + if (fifo->dch && get_next_dframe(fifo->dch)) + tx_skb = fifo->dch->tx_skb; +diff --git a/drivers/leds/leds-is31fl319x.c b/drivers/leds/leds-is31fl319x.c +index 52b59b62f437c..b2f4c4ec7c567 100644 +--- a/drivers/leds/leds-is31fl319x.c ++++ b/drivers/leds/leds-is31fl319x.c +@@ -38,6 +38,7 @@ + #define IS31FL3190_CURRENT_uA_MIN 5000 + #define IS31FL3190_CURRENT_uA_DEFAULT 42000 + #define IS31FL3190_CURRENT_uA_MAX 42000 ++#define IS31FL3190_CURRENT_SHIFT 2 + #define IS31FL3190_CURRENT_MASK GENMASK(4, 2) + #define IS31FL3190_CURRENT_5_mA 0x02 + #define IS31FL3190_CURRENT_10_mA 0x01 +@@ -553,7 +554,7 @@ static int is31fl319x_probe(struct i2c_client *client) + is31fl3196_db_to_gain(is31->audio_gain_db)); + else + regmap_update_bits(is31->regmap, IS31FL3190_CURRENT, IS31FL3190_CURRENT_MASK, +- is31fl3190_microamp_to_cs(dev, aggregated_led_microamp)); ++ is31fl3190_microamp_to_cs(dev, aggregated_led_microamp) << IS31FL3190_CURRENT_SHIFT); + + for (i = 0; i < is31->cdef->num_leds; i++) { + struct is31fl319x_led *led = &is31->leds[i]; +diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c +index 02f51cc618376..c1a56259226fb 100644 +--- a/drivers/leds/rgb/leds-qcom-lpg.c ++++ b/drivers/leds/rgb/leds-qcom-lpg.c +@@ -602,8 +602,8 @@ static void lpg_brightness_set(struct lpg_led *led, struct led_classdev *cdev, + lpg_lut_sync(lpg, lut_mask); + } + +-static void lpg_brightness_single_set(struct led_classdev *cdev, +- enum led_brightness value) ++static int lpg_brightness_single_set(struct led_classdev *cdev, ++ enum led_brightness value) + { + struct lpg_led *led = container_of(cdev, struct lpg_led, cdev); + struct mc_subled info; +@@ -614,10 +614,12 @@ static void lpg_brightness_single_set(struct led_classdev *cdev, + lpg_brightness_set(led, cdev, &info); + + mutex_unlock(&led->lpg->lock); ++ ++ return 0; + } + +-static void lpg_brightness_mc_set(struct led_classdev *cdev, +- enum led_brightness value) ++static int lpg_brightness_mc_set(struct led_classdev *cdev, ++ enum led_brightness value) + { + struct led_classdev_mc *mc = lcdev_to_mccdev(cdev); + struct lpg_led *led = container_of(mc, struct lpg_led, mcdev); +@@ -628,6 +630,8 @@ static void lpg_brightness_mc_set(struct led_classdev *cdev, + lpg_brightness_set(led, cdev, mc->subled_info); + + mutex_unlock(&led->lpg->lock); ++ ++ return 0; + } + + static int lpg_blink_set(struct lpg_led *led, +@@ -1118,7 +1122,7 @@ static int lpg_add_led(struct lpg *lpg, struct device_node *np) + led->mcdev.num_colors = num_channels; + + cdev = &led->mcdev.led_cdev; +- cdev->brightness_set = lpg_brightness_mc_set; ++ cdev->brightness_set_blocking = lpg_brightness_mc_set; + cdev->blink_set = lpg_blink_mc_set; + + /* Register pattern accessors only if we have a LUT block */ +@@ -1132,7 +1136,7 @@ static int lpg_add_led(struct lpg *lpg, struct device_node *np) + return ret; + + cdev = &led->cdev; +- cdev->brightness_set = lpg_brightness_single_set; ++ cdev->brightness_set_blocking = lpg_brightness_single_set; + cdev->blink_set = lpg_blink_single_set; + + /* Register pattern accessors only if we have a LUT block */ +@@ -1151,7 +1155,7 @@ static int lpg_add_led(struct lpg *lpg, struct device_node *np) + else + cdev->brightness = LED_OFF; + +- cdev->brightness_set(cdev, cdev->brightness); ++ cdev->brightness_set_blocking(cdev, cdev->brightness); + + init_data.fwnode = of_fwnode_handle(np); + +diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c +index 9b63bd2551c63..cd4e34d15c26b 100644 +--- a/drivers/macintosh/macio-adb.c ++++ b/drivers/macintosh/macio-adb.c +@@ -108,6 +108,10 @@ int macio_init(void) + return -ENXIO; + } + adb = ioremap(r.start, sizeof(struct adb_regs)); ++ if (!adb) { ++ of_node_put(adbs); ++ return -ENOMEM; ++ } + + out_8(&adb->ctrl.r, 0); + out_8(&adb->intr.r, 0); +diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c +index 1ec1e5984563f..3bc1f374e6577 100644 +--- a/drivers/macintosh/macio_asic.c ++++ b/drivers/macintosh/macio_asic.c +@@ -424,7 +424,7 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, + if (of_device_register(&dev->ofdev) != 0) { + printk(KERN_DEBUG"macio: device registration error for %s!\n", + dev_name(&dev->ofdev.dev)); +- kfree(dev); ++ put_device(&dev->ofdev.dev); + return NULL; + } + +diff --git a/drivers/mailbox/arm_mhuv2.c b/drivers/mailbox/arm_mhuv2.c +index a47aef8df52fd..c6d4957c4da83 100644 +--- a/drivers/mailbox/arm_mhuv2.c ++++ b/drivers/mailbox/arm_mhuv2.c +@@ -1062,8 +1062,8 @@ static int mhuv2_probe(struct amba_device *adev, const struct amba_id *id) + int ret = -EINVAL; + + reg = devm_of_iomap(dev, dev->of_node, 0, NULL); +- if (!reg) +- return -ENOMEM; ++ if (IS_ERR(reg)) ++ return PTR_ERR(reg); + + mhu = devm_kzalloc(dev, sizeof(*mhu), GFP_KERNEL); + if (!mhu) +diff --git a/drivers/mailbox/mailbox-mpfs.c b/drivers/mailbox/mailbox-mpfs.c +index cfacb3f320a64..853901acaeec2 100644 +--- a/drivers/mailbox/mailbox-mpfs.c ++++ b/drivers/mailbox/mailbox-mpfs.c +@@ -2,7 +2,7 @@ + /* + * Microchip PolarFire SoC (MPFS) system controller/mailbox controller driver + * +- * Copyright (c) 2020 Microchip Corporation. All rights reserved. ++ * Copyright (c) 2020-2022 Microchip Corporation. All rights reserved. + * + * Author: Conor Dooley <conor.dooley@microchip.com> + * +@@ -56,7 +56,7 @@ + #define SCB_STATUS_NOTIFY_MASK BIT(SCB_STATUS_NOTIFY) + + #define SCB_STATUS_POS (16) +-#define SCB_STATUS_MASK GENMASK_ULL(SCB_STATUS_POS + SCB_MASK_WIDTH, SCB_STATUS_POS) ++#define SCB_STATUS_MASK GENMASK(SCB_STATUS_POS + SCB_MASK_WIDTH - 1, SCB_STATUS_POS) + + struct mpfs_mbox { + struct mbox_controller controller; +@@ -130,13 +130,38 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan) + struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv; + struct mpfs_mss_response *response = mbox->response; + u16 num_words = ALIGN((response->resp_size), (4)) / 4U; +- u32 i; ++ u32 i, status; + + if (!response->resp_msg) { + dev_err(mbox->dev, "failed to assign memory for response %d\n", -ENOMEM); + return; + } + ++ /* ++ * The status is stored in bits 31:16 of the SERVICES_SR register. ++ * It is only valid when BUSY == 0. ++ * We should *never* get an interrupt while the controller is ++ * still in the busy state. If we do, something has gone badly ++ * wrong & the content of the mailbox would not be valid. ++ */ ++ if (mpfs_mbox_busy(mbox)) { ++ dev_err(mbox->dev, "got an interrupt but system controller is busy\n"); ++ response->resp_status = 0xDEAD; ++ return; ++ } ++ ++ status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET); ++ ++ /* ++ * If the status of the individual servers is non-zero, the service has ++ * failed. The contents of the mailbox at this point are not be valid, ++ * so don't bother reading them. Set the status so that the driver ++ * implementing the service can handle the result. ++ */ ++ response->resp_status = (status & SCB_STATUS_MASK) >> SCB_STATUS_POS; ++ if (response->resp_status) ++ return; ++ + if (!mpfs_mbox_busy(mbox)) { + for (i = 0; i < num_words; i++) { + response->resp_msg[i] = +diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c +index 3c2bc0ca454cf..105d46c9801ba 100644 +--- a/drivers/mailbox/pcc.c ++++ b/drivers/mailbox/pcc.c +@@ -743,6 +743,7 @@ static int __init pcc_init(void) + + if (IS_ERR(pcc_pdev)) { + pr_debug("Err creating PCC platform bundle\n"); ++ pcc_chan_count = 0; + return PTR_ERR(pcc_pdev); + } + +diff --git a/drivers/mailbox/zynqmp-ipi-mailbox.c b/drivers/mailbox/zynqmp-ipi-mailbox.c +index 31a0fa9142744..12e004ff1a147 100644 +--- a/drivers/mailbox/zynqmp-ipi-mailbox.c ++++ b/drivers/mailbox/zynqmp-ipi-mailbox.c +@@ -493,6 +493,7 @@ static int zynqmp_ipi_mbox_probe(struct zynqmp_ipi_mbox *ipi_mbox, + ret = device_register(&ipi_mbox->dev); + if (ret) { + dev_err(dev, "Failed to register ipi mbox dev.\n"); ++ put_device(&ipi_mbox->dev); + return ret; + } + mdev = &ipi_mbox->dev; +@@ -619,7 +620,8 @@ static void zynqmp_ipi_free_mboxes(struct zynqmp_ipi_pdata *pdata) + ipi_mbox = &pdata->ipi_mboxes[i]; + if (ipi_mbox->dev.parent) { + mbox_controller_unregister(&ipi_mbox->mbox); +- device_unregister(&ipi_mbox->dev); ++ if (device_is_registered(&ipi_mbox->dev)) ++ device_unregister(&ipi_mbox->dev); + } + } + } +diff --git a/drivers/mcb/mcb-core.c b/drivers/mcb/mcb-core.c +index 338fc889b357a..b8ad4f16b4acd 100644 +--- a/drivers/mcb/mcb-core.c ++++ b/drivers/mcb/mcb-core.c +@@ -71,8 +71,10 @@ static int mcb_probe(struct device *dev) + + get_device(dev); + ret = mdrv->probe(mdev, found_id); +- if (ret) ++ if (ret) { + module_put(carrier_mod); ++ put_device(dev); ++ } + + return ret; + } +diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c +index 0266bfddfbe27..aa6938da0db85 100644 +--- a/drivers/mcb/mcb-parse.c ++++ b/drivers/mcb/mcb-parse.c +@@ -108,7 +108,7 @@ static int chameleon_parse_gdd(struct mcb_bus *bus, + return 0; + + err: +- mcb_free_dev(mdev); ++ put_device(&mdev->dev); + + return ret; + } +diff --git a/drivers/md/dm.c b/drivers/md/dm.c +index 95a1ee3d314eb..e30c2d2bc9c78 100644 +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -732,28 +732,48 @@ static char *_dm_claim_ptr = "I belong to device-mapper"; + /* + * Open a table device so we can use it as a map destination. + */ +-static int open_table_device(struct table_device *td, dev_t dev, +- struct mapped_device *md) ++static struct table_device *open_table_device(struct mapped_device *md, ++ dev_t dev, fmode_t mode) + { ++ struct table_device *td; + struct block_device *bdev; + u64 part_off; + int r; + +- BUG_ON(td->dm_dev.bdev); ++ td = kmalloc_node(sizeof(*td), GFP_KERNEL, md->numa_node_id); ++ if (!td) ++ return ERR_PTR(-ENOMEM); ++ refcount_set(&td->count, 1); + +- bdev = blkdev_get_by_dev(dev, td->dm_dev.mode | FMODE_EXCL, _dm_claim_ptr); +- if (IS_ERR(bdev)) +- return PTR_ERR(bdev); ++ bdev = blkdev_get_by_dev(dev, mode | FMODE_EXCL, _dm_claim_ptr); ++ if (IS_ERR(bdev)) { ++ r = PTR_ERR(bdev); ++ goto out_free_td; ++ } + +- r = bd_link_disk_holder(bdev, dm_disk(md)); +- if (r) { +- blkdev_put(bdev, td->dm_dev.mode | FMODE_EXCL); +- return r; ++ /* ++ * We can be called before the dm disk is added. In that case we can't ++ * register the holder relation here. It will be done once add_disk was ++ * called. ++ */ ++ if (md->disk->slave_dir) { ++ r = bd_link_disk_holder(bdev, md->disk); ++ if (r) ++ goto out_blkdev_put; + } + ++ td->dm_dev.mode = mode; + td->dm_dev.bdev = bdev; + td->dm_dev.dax_dev = fs_dax_get_by_bdev(bdev, &part_off, NULL, NULL); +- return 0; ++ format_dev_t(td->dm_dev.name, dev); ++ list_add(&td->list, &md->table_devices); ++ return td; ++ ++out_blkdev_put: ++ blkdev_put(bdev, mode | FMODE_EXCL); ++out_free_td: ++ kfree(td); ++ return ERR_PTR(r); + } + + /* +@@ -761,14 +781,12 @@ static int open_table_device(struct table_device *td, dev_t dev, + */ + static void close_table_device(struct table_device *td, struct mapped_device *md) + { +- if (!td->dm_dev.bdev) +- return; +- +- bd_unlink_disk_holder(td->dm_dev.bdev, dm_disk(md)); ++ if (md->disk->slave_dir) ++ bd_unlink_disk_holder(td->dm_dev.bdev, md->disk); + blkdev_put(td->dm_dev.bdev, td->dm_dev.mode | FMODE_EXCL); + put_dax(td->dm_dev.dax_dev); +- td->dm_dev.bdev = NULL; +- td->dm_dev.dax_dev = NULL; ++ list_del(&td->list); ++ kfree(td); + } + + static struct table_device *find_table_device(struct list_head *l, dev_t dev, +@@ -786,31 +804,16 @@ static struct table_device *find_table_device(struct list_head *l, dev_t dev, + int dm_get_table_device(struct mapped_device *md, dev_t dev, fmode_t mode, + struct dm_dev **result) + { +- int r; + struct table_device *td; + + mutex_lock(&md->table_devices_lock); + td = find_table_device(&md->table_devices, dev, mode); + if (!td) { +- td = kmalloc_node(sizeof(*td), GFP_KERNEL, md->numa_node_id); +- if (!td) { ++ td = open_table_device(md, dev, mode); ++ if (IS_ERR(td)) { + mutex_unlock(&md->table_devices_lock); +- return -ENOMEM; ++ return PTR_ERR(td); + } +- +- td->dm_dev.mode = mode; +- td->dm_dev.bdev = NULL; +- +- if ((r = open_table_device(td, dev, md))) { +- mutex_unlock(&md->table_devices_lock); +- kfree(td); +- return r; +- } +- +- format_dev_t(td->dm_dev.name, dev); +- +- refcount_set(&td->count, 1); +- list_add(&td->list, &md->table_devices); + } else { + refcount_inc(&td->count); + } +@@ -825,11 +828,8 @@ void dm_put_table_device(struct mapped_device *md, struct dm_dev *d) + struct table_device *td = container_of(d, struct table_device, dm_dev); + + mutex_lock(&md->table_devices_lock); +- if (refcount_dec_and_test(&td->count)) { ++ if (refcount_dec_and_test(&td->count)) + close_table_device(td, md); +- list_del(&td->list); +- kfree(td); +- } + mutex_unlock(&md->table_devices_lock); + } + +@@ -1972,8 +1972,21 @@ static void cleanup_mapped_device(struct mapped_device *md) + md->disk->private_data = NULL; + spin_unlock(&_minor_lock); + if (dm_get_md_type(md) != DM_TYPE_NONE) { ++ struct table_device *td; ++ + dm_sysfs_exit(md); ++ list_for_each_entry(td, &md->table_devices, list) { ++ bd_unlink_disk_holder(td->dm_dev.bdev, ++ md->disk); ++ } ++ ++ /* ++ * Hold lock to make sure del_gendisk() won't concurrent ++ * with open/close_table_device(). ++ */ ++ mutex_lock(&md->table_devices_lock); + del_gendisk(md->disk); ++ mutex_unlock(&md->table_devices_lock); + } + dm_queue_destroy_crypto_profile(md->queue); + put_disk(md->disk); +@@ -2305,6 +2318,7 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t) + { + enum dm_queue_mode type = dm_table_get_type(t); + struct queue_limits limits; ++ struct table_device *td; + int r; + + switch (type) { +@@ -2333,17 +2347,40 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t) + if (r) + return r; + ++ /* ++ * Hold lock to make sure add_disk() and del_gendisk() won't concurrent ++ * with open_table_device() and close_table_device(). ++ */ ++ mutex_lock(&md->table_devices_lock); + r = add_disk(md->disk); ++ mutex_unlock(&md->table_devices_lock); + if (r) + return r; + +- r = dm_sysfs_init(md); +- if (r) { +- del_gendisk(md->disk); +- return r; ++ /* ++ * Register the holder relationship for devices added before the disk ++ * was live. ++ */ ++ list_for_each_entry(td, &md->table_devices, list) { ++ r = bd_link_disk_holder(td->dm_dev.bdev, md->disk); ++ if (r) ++ goto out_undo_holders; + } ++ ++ r = dm_sysfs_init(md); ++ if (r) ++ goto out_undo_holders; ++ + md->type = type; + return 0; ++ ++out_undo_holders: ++ list_for_each_entry_continue_reverse(td, &md->table_devices, list) ++ bd_unlink_disk_holder(td->dm_dev.bdev, md->disk); ++ mutex_lock(&md->table_devices_lock); ++ del_gendisk(md->disk); ++ mutex_unlock(&md->table_devices_lock); ++ return r; + } + + struct mapped_device *dm_get_md(dev_t dev) +diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c +index bf6dffadbe6f6..63ece30114e53 100644 +--- a/drivers/md/md-bitmap.c ++++ b/drivers/md/md-bitmap.c +@@ -2195,20 +2195,23 @@ int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks, + + if (set) { + bmc_new = md_bitmap_get_counter(&bitmap->counts, block, &new_blocks, 1); +- if (*bmc_new == 0) { +- /* need to set on-disk bits too. */ +- sector_t end = block + new_blocks; +- sector_t start = block >> chunkshift; +- start <<= chunkshift; +- while (start < end) { +- md_bitmap_file_set_bit(bitmap, block); +- start += 1 << chunkshift; ++ if (bmc_new) { ++ if (*bmc_new == 0) { ++ /* need to set on-disk bits too. */ ++ sector_t end = block + new_blocks; ++ sector_t start = block >> chunkshift; ++ ++ start <<= chunkshift; ++ while (start < end) { ++ md_bitmap_file_set_bit(bitmap, block); ++ start += 1 << chunkshift; ++ } ++ *bmc_new = 2; ++ md_bitmap_count_page(&bitmap->counts, block, 1); ++ md_bitmap_set_pending(&bitmap->counts, block); + } +- *bmc_new = 2; +- md_bitmap_count_page(&bitmap->counts, block, 1); +- md_bitmap_set_pending(&bitmap->counts, block); ++ *bmc_new |= NEEDED_MASK; + } +- *bmc_new |= NEEDED_MASK; + if (new_blocks < old_blocks) + old_blocks = new_blocks; + } +diff --git a/drivers/md/md.c b/drivers/md/md.c +index a467b492d4ad3..fd82881761d34 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -509,13 +509,14 @@ static void md_end_flush(struct bio *bio) + struct md_rdev *rdev = bio->bi_private; + struct mddev *mddev = rdev->mddev; + ++ bio_put(bio); ++ + rdev_dec_pending(rdev, mddev); + + if (atomic_dec_and_test(&mddev->flush_pending)) { + /* The pre-request flush has finished */ + queue_work(md_wq, &mddev->flush_work); + } +- bio_put(bio); + } + + static void md_submit_flush_data(struct work_struct *ws); +@@ -913,10 +914,12 @@ static void super_written(struct bio *bio) + } else + clear_bit(LastDev, &rdev->flags); + ++ bio_put(bio); ++ ++ rdev_dec_pending(rdev, mddev); ++ + if (atomic_dec_and_test(&mddev->pending_writes)) + wake_up(&mddev->sb_wait); +- rdev_dec_pending(rdev, mddev); +- bio_put(bio); + } + + void md_super_write(struct mddev *mddev, struct md_rdev *rdev, +diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c +index 857c49399c28e..b536befd88988 100644 +--- a/drivers/md/raid0.c ++++ b/drivers/md/raid0.c +@@ -398,7 +398,6 @@ static int raid0_run(struct mddev *mddev) + + blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors); + blk_queue_max_write_zeroes_sectors(mddev->queue, mddev->chunk_sectors); +- blk_queue_max_discard_sectors(mddev->queue, UINT_MAX); + + blk_queue_io_min(mddev->queue, mddev->chunk_sectors << 9); + blk_queue_io_opt(mddev->queue, +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 05d8438cfec88..58f705f429480 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -3159,6 +3159,7 @@ static int raid1_run(struct mddev *mddev) + * RAID1 needs at least one disk in active + */ + if (conf->raid_disks - mddev->degraded < 1) { ++ md_unregister_thread(&conf->thread); + ret = -EINVAL; + goto abort; + } +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index 3aa8b6e11d585..9a6503f5cb982 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -4145,8 +4145,6 @@ static int raid10_run(struct mddev *mddev) + conf->thread = NULL; + + if (mddev->queue) { +- blk_queue_max_discard_sectors(mddev->queue, +- UINT_MAX); + blk_queue_max_write_zeroes_sectors(mddev->queue, 0); + blk_queue_io_min(mddev->queue, mddev->chunk_sectors << 9); + raid10_set_io_opt(conf); +diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb-core/dvb_ca_en50221.c +index 15a08d8c69ef8..c2d2792227f86 100644 +--- a/drivers/media/dvb-core/dvb_ca_en50221.c ++++ b/drivers/media/dvb-core/dvb_ca_en50221.c +@@ -157,7 +157,7 @@ static void dvb_ca_private_free(struct dvb_ca_private *ca) + { + unsigned int i; + +- dvb_free_device(ca->dvbdev); ++ dvb_device_put(ca->dvbdev); + for (i = 0; i < ca->slot_count; i++) + vfree(ca->slot_info[i].rx_buffer.data); + +diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c +index 48e735cdbe6bb..c41a7e5c2b928 100644 +--- a/drivers/media/dvb-core/dvb_frontend.c ++++ b/drivers/media/dvb-core/dvb_frontend.c +@@ -136,7 +136,7 @@ static void __dvb_frontend_free(struct dvb_frontend *fe) + struct dvb_frontend_private *fepriv = fe->frontend_priv; + + if (fepriv) +- dvb_free_device(fepriv->dvbdev); ++ dvb_device_put(fepriv->dvbdev); + + dvb_frontend_invoke_release(fe, fe->ops.release); + +@@ -2986,6 +2986,7 @@ int dvb_register_frontend(struct dvb_adapter *dvb, + .name = fe->ops.info.name, + #endif + }; ++ int ret; + + dev_dbg(dvb->device, "%s:\n", __func__); + +@@ -3019,8 +3020,13 @@ int dvb_register_frontend(struct dvb_adapter *dvb, + "DVB: registering adapter %i frontend %i (%s)...\n", + fe->dvb->num, fe->id, fe->ops.info.name); + +- dvb_register_device(fe->dvb, &fepriv->dvbdev, &dvbdev_template, ++ ret = dvb_register_device(fe->dvb, &fepriv->dvbdev, &dvbdev_template, + fe, DVB_DEVICE_FRONTEND, 0); ++ if (ret) { ++ dvb_frontend_put(fe); ++ mutex_unlock(&frontend_mutex); ++ return ret; ++ } + + /* + * Initialize the cache to the proper values according with the +diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c +index 675d877a67b25..9934728734af9 100644 +--- a/drivers/media/dvb-core/dvbdev.c ++++ b/drivers/media/dvb-core/dvbdev.c +@@ -97,7 +97,7 @@ static int dvb_device_open(struct inode *inode, struct file *file) + new_fops = fops_get(dvbdev->fops); + if (!new_fops) + goto fail; +- file->private_data = dvbdev; ++ file->private_data = dvb_device_get(dvbdev); + replace_fops(file, new_fops); + if (file->f_op->open) + err = file->f_op->open(inode, file); +@@ -161,6 +161,9 @@ int dvb_generic_release(struct inode *inode, struct file *file) + } + + dvbdev->users++; ++ ++ dvb_device_put(dvbdev); ++ + return 0; + } + EXPORT_SYMBOL(dvb_generic_release); +@@ -478,6 +481,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, + } + + memcpy(dvbdev, template, sizeof(struct dvb_device)); ++ kref_init(&dvbdev->ref); + dvbdev->type = type; + dvbdev->id = id; + dvbdev->adapter = adap; +@@ -508,7 +512,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, + #endif + + dvbdev->minor = minor; +- dvb_minors[minor] = dvbdev; ++ dvb_minors[minor] = dvb_device_get(dvbdev); + up_write(&minor_rwsem); + + ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads); +@@ -553,6 +557,7 @@ void dvb_remove_device(struct dvb_device *dvbdev) + + down_write(&minor_rwsem); + dvb_minors[dvbdev->minor] = NULL; ++ dvb_device_put(dvbdev); + up_write(&minor_rwsem); + + dvb_media_device_free(dvbdev); +@@ -564,21 +569,34 @@ void dvb_remove_device(struct dvb_device *dvbdev) + EXPORT_SYMBOL(dvb_remove_device); + + +-void dvb_free_device(struct dvb_device *dvbdev) ++static void dvb_free_device(struct kref *ref) + { +- if (!dvbdev) +- return; ++ struct dvb_device *dvbdev = container_of(ref, struct dvb_device, ref); + + kfree (dvbdev->fops); + kfree (dvbdev); + } +-EXPORT_SYMBOL(dvb_free_device); ++ ++ ++struct dvb_device *dvb_device_get(struct dvb_device *dvbdev) ++{ ++ kref_get(&dvbdev->ref); ++ return dvbdev; ++} ++EXPORT_SYMBOL(dvb_device_get); ++ ++ ++void dvb_device_put(struct dvb_device *dvbdev) ++{ ++ if (dvbdev) ++ kref_put(&dvbdev->ref, dvb_free_device); ++} + + + void dvb_unregister_device(struct dvb_device *dvbdev) + { + dvb_remove_device(dvbdev); +- dvb_free_device(dvbdev); ++ dvb_device_put(dvbdev); + } + EXPORT_SYMBOL(dvb_unregister_device); + +diff --git a/drivers/media/dvb-frontends/bcm3510.c b/drivers/media/dvb-frontends/bcm3510.c +index da0ff7b44da41..68b92b4419cff 100644 +--- a/drivers/media/dvb-frontends/bcm3510.c ++++ b/drivers/media/dvb-frontends/bcm3510.c +@@ -649,6 +649,7 @@ static int bcm3510_download_firmware(struct dvb_frontend* fe) + deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04zx\n",addr,len,fw->size); + if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) { + err("firmware download failed: %d\n",ret); ++ release_firmware(fw); + return ret; + } + i += 4 + len; +diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c +index 516de278cc493..a12fedcc3a1ce 100644 +--- a/drivers/media/i2c/ad5820.c ++++ b/drivers/media/i2c/ad5820.c +@@ -327,18 +327,18 @@ static int ad5820_probe(struct i2c_client *client, + + ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL); + if (ret < 0) +- goto cleanup2; ++ goto clean_mutex; + + ret = v4l2_async_register_subdev(&coil->subdev); + if (ret < 0) +- goto cleanup; ++ goto clean_entity; + + return ret; + +-cleanup2: +- mutex_destroy(&coil->power_lock); +-cleanup: ++clean_entity: + media_entity_cleanup(&coil->subdev.entity); ++clean_mutex: ++ mutex_destroy(&coil->power_lock); + return ret; + } + +diff --git a/drivers/media/i2c/adv748x/adv748x-afe.c b/drivers/media/i2c/adv748x/adv748x-afe.c +index 02eabe10ab970..00095c7762c24 100644 +--- a/drivers/media/i2c/adv748x/adv748x-afe.c ++++ b/drivers/media/i2c/adv748x/adv748x-afe.c +@@ -521,6 +521,10 @@ int adv748x_afe_init(struct adv748x_afe *afe) + } + } + ++ adv748x_afe_s_input(afe, afe->input); ++ ++ adv_dbg(state, "AFE Default input set to %d\n", afe->input); ++ + /* Entity pads and sinks are 0-indexed to match the pads */ + for (i = ADV748X_AFE_SINK_AIN0; i <= ADV748X_AFE_SINK_AIN7; i++) + afe->pads[i].flags = MEDIA_PAD_FL_SINK; +diff --git a/drivers/media/i2c/dw9768.c b/drivers/media/i2c/dw9768.c +index 0f47ef015a1d3..83a3ee275bbe8 100644 +--- a/drivers/media/i2c/dw9768.c ++++ b/drivers/media/i2c/dw9768.c +@@ -414,6 +414,7 @@ static int dw9768_probe(struct i2c_client *client) + { + struct device *dev = &client->dev; + struct dw9768 *dw9768; ++ bool full_power; + unsigned int i; + int ret; + +@@ -469,13 +470,23 @@ static int dw9768_probe(struct i2c_client *client) + + dw9768->sd.entity.function = MEDIA_ENT_F_LENS; + ++ /* ++ * Figure out whether we're going to power up the device here. Generally ++ * this is done if CONFIG_PM is disabled in a DT system or the device is ++ * to be powered on in an ACPI system. Similarly for power off in ++ * remove. ++ */ + pm_runtime_enable(dev); +- if (!pm_runtime_enabled(dev)) { ++ full_power = (is_acpi_node(dev_fwnode(dev)) && ++ acpi_dev_state_d0(dev)) || ++ (is_of_node(dev_fwnode(dev)) && !pm_runtime_enabled(dev)); ++ if (full_power) { + ret = dw9768_runtime_resume(dev); + if (ret < 0) { + dev_err(dev, "failed to power on: %d\n", ret); + goto err_clean_entity; + } ++ pm_runtime_set_active(dev); + } + + ret = v4l2_async_register_subdev(&dw9768->sd); +@@ -484,14 +495,17 @@ static int dw9768_probe(struct i2c_client *client) + goto err_power_off; + } + ++ pm_runtime_idle(dev); ++ + return 0; + + err_power_off: +- if (pm_runtime_enabled(dev)) +- pm_runtime_disable(dev); +- else ++ if (full_power) { + dw9768_runtime_suspend(dev); ++ pm_runtime_set_suspended(dev); ++ } + err_clean_entity: ++ pm_runtime_disable(dev); + media_entity_cleanup(&dw9768->sd.entity); + err_free_handler: + v4l2_ctrl_handler_free(&dw9768->ctrls); +@@ -503,14 +517,17 @@ static void dw9768_remove(struct i2c_client *client) + { + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct dw9768 *dw9768 = sd_to_dw9768(sd); ++ struct device *dev = &client->dev; + + v4l2_async_unregister_subdev(&dw9768->sd); + v4l2_ctrl_handler_free(&dw9768->ctrls); + media_entity_cleanup(&dw9768->sd.entity); +- pm_runtime_disable(&client->dev); +- if (!pm_runtime_status_suspended(&client->dev)) +- dw9768_runtime_suspend(&client->dev); +- pm_runtime_set_suspended(&client->dev); ++ if ((is_acpi_node(dev_fwnode(dev)) && acpi_dev_state_d0(dev)) || ++ (is_of_node(dev_fwnode(dev)) && !pm_runtime_enabled(dev))) { ++ dw9768_runtime_suspend(dev); ++ pm_runtime_set_suspended(dev); ++ } ++ pm_runtime_disable(dev); + } + + static const struct of_device_id dw9768_of_table[] = { +diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c +index c5b69823f257e..7c61873b71981 100644 +--- a/drivers/media/i2c/hi846.c ++++ b/drivers/media/i2c/hi846.c +@@ -2008,22 +2008,24 @@ static int hi846_parse_dt(struct hi846 *hi846, struct device *dev) + bus_cfg.bus.mipi_csi2.num_data_lanes != 4) { + dev_err(dev, "number of CSI2 data lanes %d is not supported", + bus_cfg.bus.mipi_csi2.num_data_lanes); +- v4l2_fwnode_endpoint_free(&bus_cfg); +- return -EINVAL; ++ ret = -EINVAL; ++ goto check_hwcfg_error; + } + + hi846->nr_lanes = bus_cfg.bus.mipi_csi2.num_data_lanes; + + if (!bus_cfg.nr_of_link_frequencies) { + dev_err(dev, "link-frequency property not found in DT\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto check_hwcfg_error; + } + + /* Check that link frequences for all the modes are in device tree */ + fq = hi846_check_link_freqs(hi846, &bus_cfg); + if (fq) { + dev_err(dev, "Link frequency of %lld is not supported\n", fq); +- return -EINVAL; ++ ret = -EINVAL; ++ goto check_hwcfg_error; + } + + v4l2_fwnode_endpoint_free(&bus_cfg); +@@ -2044,6 +2046,10 @@ static int hi846_parse_dt(struct hi846 *hi846, struct device *dev) + } + + return 0; ++ ++check_hwcfg_error: ++ v4l2_fwnode_endpoint_free(&bus_cfg); ++ return ret; + } + + static int hi846_probe(struct i2c_client *client) +diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c +index 45f7b5e52bc39..b69db6fc82618 100644 +--- a/drivers/media/i2c/mt9p031.c ++++ b/drivers/media/i2c/mt9p031.c +@@ -702,7 +702,6 @@ static int mt9p031_init_cfg(struct v4l2_subdev *subdev, + V4L2_SUBDEV_FORMAT_TRY; + + crop = __mt9p031_get_pad_crop(mt9p031, sd_state, 0, which); +- v4l2_subdev_get_try_crop(subdev, sd_state, 0); + crop->left = MT9P031_COLUMN_START_DEF; + crop->top = MT9P031_ROW_START_DEF; + crop->width = MT9P031_WINDOW_WIDTH_DEF; +diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c +index 2d740397a5d4d..3f6d715efa823 100644 +--- a/drivers/media/i2c/ov5640.c ++++ b/drivers/media/i2c/ov5640.c +@@ -3817,7 +3817,8 @@ static int ov5640_probe(struct i2c_client *client) + sensor->current_mode = + &ov5640_mode_data[OV5640_MODE_VGA_640_480]; + sensor->last_mode = sensor->current_mode; +- sensor->current_link_freq = OV5640_DEFAULT_LINK_FREQ; ++ sensor->current_link_freq = ++ ov5640_csi2_link_freqs[OV5640_DEFAULT_LINK_FREQ]; + + sensor->ae_target = 52; + +diff --git a/drivers/media/i2c/ov5648.c b/drivers/media/i2c/ov5648.c +index 84604ea7bdf9e..17465fcf28e33 100644 +--- a/drivers/media/i2c/ov5648.c ++++ b/drivers/media/i2c/ov5648.c +@@ -2597,6 +2597,7 @@ static void ov5648_remove(struct i2c_client *client) + v4l2_ctrl_handler_free(&sensor->ctrls.handler); + mutex_destroy(&sensor->mutex); + media_entity_cleanup(&subdev->entity); ++ v4l2_fwnode_endpoint_free(&sensor->endpoint); + } + + static const struct dev_pm_ops ov5648_pm_ops = { +diff --git a/drivers/media/pci/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c +index d5f32e3ff5441..754c8be1b6d8b 100644 +--- a/drivers/media/pci/saa7164/saa7164-core.c ++++ b/drivers/media/pci/saa7164/saa7164-core.c +@@ -1259,7 +1259,7 @@ static int saa7164_initdev(struct pci_dev *pci_dev, + + if (saa7164_dev_setup(dev) < 0) { + err = -EINVAL; +- goto fail_free; ++ goto fail_dev; + } + + /* print pci info */ +@@ -1427,6 +1427,8 @@ fail_fw: + + fail_irq: + saa7164_dev_unregister(dev); ++fail_dev: ++ pci_disable_device(pci_dev); + fail_free: + v4l2_device_unregister(&dev->v4l2_dev); + kfree(dev); +diff --git a/drivers/media/pci/solo6x10/solo6x10-core.c b/drivers/media/pci/solo6x10/solo6x10-core.c +index 4a546eeefe38f..6d87fbb0ee04a 100644 +--- a/drivers/media/pci/solo6x10/solo6x10-core.c ++++ b/drivers/media/pci/solo6x10/solo6x10-core.c +@@ -420,6 +420,7 @@ static int solo_sysfs_init(struct solo_dev *solo_dev) + solo_dev->nr_chans); + + if (device_register(dev)) { ++ put_device(dev); + dev->parent = NULL; + return -ENOMEM; + } +diff --git a/drivers/media/platform/amphion/vdec.c b/drivers/media/platform/amphion/vdec.c +index feb75dc204de8..b27e6bed85f0f 100644 +--- a/drivers/media/platform/amphion/vdec.c ++++ b/drivers/media/platform/amphion/vdec.c +@@ -286,6 +286,7 @@ static int vdec_g_fmt(struct file *file, void *fh, struct v4l2_format *f) + struct vpu_format *cur_fmt; + int i; + ++ vpu_inst_lock(inst); + cur_fmt = vpu_get_format(inst, f->type); + + pixmp->pixelformat = cur_fmt->pixfmt; +@@ -303,6 +304,7 @@ static int vdec_g_fmt(struct file *file, void *fh, struct v4l2_format *f) + f->fmt.pix_mp.xfer_func = vdec->codec_info.transfer_chars; + f->fmt.pix_mp.ycbcr_enc = vdec->codec_info.matrix_coeffs; + f->fmt.pix_mp.quantization = vdec->codec_info.full_range; ++ vpu_inst_unlock(inst); + + return 0; + } +@@ -753,6 +755,9 @@ static bool vdec_check_source_change(struct vpu_inst *inst) + if (!inst->fh.m2m_ctx) + return false; + ++ if (vdec->reset_codec) ++ return false; ++ + if (!vb2_is_streaming(v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx))) + return true; + fmt = vpu_helper_find_format(inst, inst->cap_format.type, vdec->codec_info.pixfmt); +@@ -1088,7 +1093,8 @@ static void vdec_event_seq_hdr(struct vpu_inst *inst, struct vpu_dec_codec_info + vdec->seq_tag = vdec->codec_info.tag; + if (vdec->is_source_changed) { + vdec_update_state(inst, VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE, 0); +- vpu_notify_source_change(inst); ++ vdec->source_change++; ++ vdec_handle_resolution_change(inst); + vdec->is_source_changed = false; + } + } +@@ -1335,6 +1341,8 @@ static void vdec_abort(struct vpu_inst *inst) + vdec->decoded_frame_count, + vdec->display_frame_count, + vdec->sequence); ++ if (!vdec->seq_hdr_found) ++ vdec->reset_codec = true; + vdec->params.end_flag = 0; + vdec->drain = 0; + vdec->params.frame_count = 0; +@@ -1342,6 +1350,7 @@ static void vdec_abort(struct vpu_inst *inst) + vdec->display_frame_count = 0; + vdec->sequence = 0; + vdec->aborting = false; ++ inst->extra_size = 0; + } + + static void vdec_stop(struct vpu_inst *inst, bool free) +@@ -1464,8 +1473,7 @@ static int vdec_start_session(struct vpu_inst *inst, u32 type) + } + + if (V4L2_TYPE_IS_OUTPUT(type)) { +- if (inst->state == VPU_CODEC_STATE_SEEK) +- vdec_update_state(inst, vdec->state, 1); ++ vdec_update_state(inst, vdec->state, 1); + vdec->eos_received = 0; + vpu_process_output_buffer(inst); + } else { +@@ -1629,6 +1637,7 @@ static int vdec_open(struct file *file) + return ret; + + vdec->fixed_fmt = false; ++ vdec->state = VPU_CODEC_STATE_ACTIVE; + inst->min_buffer_cap = VDEC_MIN_BUFFER_CAP; + inst->min_buffer_out = VDEC_MIN_BUFFER_OUT; + vdec_init(file); +diff --git a/drivers/media/platform/amphion/vpu.h b/drivers/media/platform/amphion/vpu.h +index beac0309ca8d9..048c23c2bf4db 100644 +--- a/drivers/media/platform/amphion/vpu.h ++++ b/drivers/media/platform/amphion/vpu.h +@@ -13,6 +13,7 @@ + #include <linux/mailbox_controller.h> + #include <linux/kfifo.h> + ++#define VPU_TIMEOUT_WAKEUP msecs_to_jiffies(200) + #define VPU_TIMEOUT msecs_to_jiffies(1000) + #define VPU_INST_NULL_ID (-1L) + #define VPU_MSG_BUFFER_SIZE (8192) +diff --git a/drivers/media/platform/amphion/vpu_cmds.c b/drivers/media/platform/amphion/vpu_cmds.c +index f4d7ca78a6212..fa581ba6bab2d 100644 +--- a/drivers/media/platform/amphion/vpu_cmds.c ++++ b/drivers/media/platform/amphion/vpu_cmds.c +@@ -269,7 +269,7 @@ exit: + return flag; + } + +-static int sync_session_response(struct vpu_inst *inst, unsigned long key) ++static int sync_session_response(struct vpu_inst *inst, unsigned long key, long timeout, int try) + { + struct vpu_core *core; + +@@ -279,10 +279,12 @@ static int sync_session_response(struct vpu_inst *inst, unsigned long key) + core = inst->core; + + call_void_vop(inst, wait_prepare); +- wait_event_timeout(core->ack_wq, check_is_responsed(inst, key), VPU_TIMEOUT); ++ wait_event_timeout(core->ack_wq, check_is_responsed(inst, key), timeout); + call_void_vop(inst, wait_finish); + + if (!check_is_responsed(inst, key)) { ++ if (try) ++ return -EINVAL; + dev_err(inst->dev, "[%d] sync session timeout\n", inst->id); + set_bit(inst->id, &core->hang_mask); + mutex_lock(&inst->core->cmd_lock); +@@ -294,6 +296,19 @@ static int sync_session_response(struct vpu_inst *inst, unsigned long key) + return 0; + } + ++static void vpu_core_keep_active(struct vpu_core *core) ++{ ++ struct vpu_rpc_event pkt; ++ ++ memset(&pkt, 0, sizeof(pkt)); ++ vpu_iface_pack_cmd(core, &pkt, 0, VPU_CMD_ID_NOOP, NULL); ++ ++ dev_dbg(core->dev, "try to wake up\n"); ++ mutex_lock(&core->cmd_lock); ++ vpu_cmd_send(core, &pkt); ++ mutex_unlock(&core->cmd_lock); ++} ++ + static int vpu_session_send_cmd(struct vpu_inst *inst, u32 id, void *data) + { + unsigned long key; +@@ -304,9 +319,25 @@ static int vpu_session_send_cmd(struct vpu_inst *inst, u32 id, void *data) + return -EINVAL; + + ret = vpu_request_cmd(inst, id, data, &key, &sync); +- if (!ret && sync) +- ret = sync_session_response(inst, key); ++ if (ret) ++ goto exit; ++ ++ /* workaround for a firmware issue, ++ * firmware should be waked up by start or configure command, ++ * but there is a very small change that firmware failed to wakeup. ++ * in such case, try to wakeup firmware again by sending a noop command ++ */ ++ if (sync && (id == VPU_CMD_ID_CONFIGURE_CODEC || id == VPU_CMD_ID_START)) { ++ if (sync_session_response(inst, key, VPU_TIMEOUT_WAKEUP, 1)) ++ vpu_core_keep_active(inst->core); ++ else ++ goto exit; ++ } ++ ++ if (sync) ++ ret = sync_session_response(inst, key, VPU_TIMEOUT, 0); + ++exit: + if (ret) + dev_err(inst->dev, "[%d] send cmd(0x%x) fail\n", inst->id, id); + +diff --git a/drivers/media/platform/amphion/vpu_drv.c b/drivers/media/platform/amphion/vpu_drv.c +index 9d5a5075343d3..f01ce49d27e80 100644 +--- a/drivers/media/platform/amphion/vpu_drv.c ++++ b/drivers/media/platform/amphion/vpu_drv.c +@@ -245,7 +245,11 @@ static int __init vpu_driver_init(void) + if (ret) + return ret; + +- return vpu_core_driver_init(); ++ ret = vpu_core_driver_init(); ++ if (ret) ++ platform_driver_unregister(&hion_vpu_driver); ++ ++ return ret; + } + + static void __exit vpu_driver_exit(void) +diff --git a/drivers/media/platform/amphion/vpu_malone.c b/drivers/media/platform/amphion/vpu_malone.c +index 51e0702f9ae17..9f2890730fd70 100644 +--- a/drivers/media/platform/amphion/vpu_malone.c ++++ b/drivers/media/platform/amphion/vpu_malone.c +@@ -692,6 +692,7 @@ int vpu_malone_set_decode_params(struct vpu_shared_addr *shared, + } + + static struct vpu_pair malone_cmds[] = { ++ {VPU_CMD_ID_NOOP, VID_API_CMD_NULL}, + {VPU_CMD_ID_START, VID_API_CMD_START}, + {VPU_CMD_ID_STOP, VID_API_CMD_STOP}, + {VPU_CMD_ID_ABORT, VID_API_CMD_ABORT}, +diff --git a/drivers/media/platform/amphion/vpu_msgs.c b/drivers/media/platform/amphion/vpu_msgs.c +index d8247f36d84ba..92672a802b492 100644 +--- a/drivers/media/platform/amphion/vpu_msgs.c ++++ b/drivers/media/platform/amphion/vpu_msgs.c +@@ -43,6 +43,7 @@ static void vpu_session_handle_mem_request(struct vpu_inst *inst, struct vpu_rpc + req_data.ref_frame_num, + req_data.act_buf_size, + req_data.act_buf_num); ++ vpu_inst_lock(inst); + call_void_vop(inst, mem_request, + req_data.enc_frame_size, + req_data.enc_frame_num, +@@ -50,6 +51,7 @@ static void vpu_session_handle_mem_request(struct vpu_inst *inst, struct vpu_rpc + req_data.ref_frame_num, + req_data.act_buf_size, + req_data.act_buf_num); ++ vpu_inst_unlock(inst); + } + + static void vpu_session_handle_stop_done(struct vpu_inst *inst, struct vpu_rpc_event *pkt) +diff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c +index b779e0ba916ca..590d1084e5a5d 100644 +--- a/drivers/media/platform/amphion/vpu_v4l2.c ++++ b/drivers/media/platform/amphion/vpu_v4l2.c +@@ -65,18 +65,11 @@ unsigned int vpu_get_buffer_state(struct vb2_v4l2_buffer *vbuf) + + void vpu_v4l2_set_error(struct vpu_inst *inst) + { +- struct vb2_queue *src_q; +- struct vb2_queue *dst_q; +- + vpu_inst_lock(inst); + dev_err(inst->dev, "some error occurs in codec\n"); + if (inst->fh.m2m_ctx) { +- src_q = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx); +- dst_q = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx); +- src_q->error = 1; +- dst_q->error = 1; +- wake_up(&src_q->done_wq); +- wake_up(&dst_q->done_wq); ++ vb2_queue_error(v4l2_m2m_get_src_vq(inst->fh.m2m_ctx)); ++ vb2_queue_error(v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx)); + } + vpu_inst_unlock(inst); + } +@@ -249,8 +242,12 @@ int vpu_process_capture_buffer(struct vpu_inst *inst) + + struct vb2_v4l2_buffer *vpu_next_src_buf(struct vpu_inst *inst) + { +- struct vb2_v4l2_buffer *src_buf = v4l2_m2m_next_src_buf(inst->fh.m2m_ctx); ++ struct vb2_v4l2_buffer *src_buf = NULL; ++ ++ if (!inst->fh.m2m_ctx) ++ return NULL; + ++ src_buf = v4l2_m2m_next_src_buf(inst->fh.m2m_ctx); + if (!src_buf || vpu_get_buffer_state(src_buf) == VPU_BUF_STATE_IDLE) + return NULL; + +@@ -273,7 +270,7 @@ void vpu_skip_frame(struct vpu_inst *inst, int count) + enum vb2_buffer_state state; + int i = 0; + +- if (count <= 0) ++ if (count <= 0 || !inst->fh.m2m_ctx) + return; + + while (i < count) { +@@ -603,10 +600,6 @@ static int vpu_v4l2_release(struct vpu_inst *inst) + inst->workqueue = NULL; + } + +- if (inst->fh.m2m_ctx) { +- v4l2_m2m_ctx_release(inst->fh.m2m_ctx); +- inst->fh.m2m_ctx = NULL; +- } + v4l2_ctrl_handler_free(&inst->ctrl_handler); + mutex_destroy(&inst->lock); + v4l2_fh_del(&inst->fh); +@@ -689,6 +682,13 @@ int vpu_v4l2_close(struct file *file) + + vpu_trace(vpu->dev, "tgid = %d, pid = %d, inst = %p\n", inst->tgid, inst->pid, inst); + ++ vpu_inst_lock(inst); ++ if (inst->fh.m2m_ctx) { ++ v4l2_m2m_ctx_release(inst->fh.m2m_ctx); ++ inst->fh.m2m_ctx = NULL; ++ } ++ vpu_inst_unlock(inst); ++ + call_void_vop(inst, release); + vpu_inst_unregister(inst); + vpu_inst_put(inst); +diff --git a/drivers/media/platform/amphion/vpu_windsor.c b/drivers/media/platform/amphion/vpu_windsor.c +index 1526af2ef9da4..b93c8cfdee7f5 100644 +--- a/drivers/media/platform/amphion/vpu_windsor.c ++++ b/drivers/media/platform/amphion/vpu_windsor.c +@@ -658,6 +658,7 @@ int vpu_windsor_get_stream_buffer_size(struct vpu_shared_addr *shared) + } + + static struct vpu_pair windsor_cmds[] = { ++ {VPU_CMD_ID_NOOP, GTB_ENC_CMD_NOOP}, + {VPU_CMD_ID_CONFIGURE_CODEC, GTB_ENC_CMD_CONFIGURE_CODEC}, + {VPU_CMD_ID_START, GTB_ENC_CMD_STREAM_START}, + {VPU_CMD_ID_STOP, GTB_ENC_CMD_STREAM_STOP}, +diff --git a/drivers/media/platform/chips-media/coda-bit.c b/drivers/media/platform/chips-media/coda-bit.c +index 2736a902e3df3..ed47d5bd8d61e 100644 +--- a/drivers/media/platform/chips-media/coda-bit.c ++++ b/drivers/media/platform/chips-media/coda-bit.c +@@ -854,7 +854,7 @@ static void coda_setup_iram(struct coda_ctx *ctx) + /* Only H.264BP and H.263P3 are considered */ + iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, w64); + iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, w64); +- if (!iram_info->buf_dbk_c_use) ++ if (!iram_info->buf_dbk_y_use || !iram_info->buf_dbk_c_use) + goto out; + iram_info->axi_sram_use |= dbk_bits; + +@@ -878,7 +878,7 @@ static void coda_setup_iram(struct coda_ctx *ctx) + + iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, w128); + iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, w128); +- if (!iram_info->buf_dbk_c_use) ++ if (!iram_info->buf_dbk_y_use || !iram_info->buf_dbk_c_use) + goto out; + iram_info->axi_sram_use |= dbk_bits; + +@@ -1084,10 +1084,16 @@ static int coda_start_encoding(struct coda_ctx *ctx) + } + + if (dst_fourcc == V4L2_PIX_FMT_JPEG) { +- if (!ctx->params.jpeg_qmat_tab[0]) ++ if (!ctx->params.jpeg_qmat_tab[0]) { + ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL); +- if (!ctx->params.jpeg_qmat_tab[1]) ++ if (!ctx->params.jpeg_qmat_tab[0]) ++ return -ENOMEM; ++ } ++ if (!ctx->params.jpeg_qmat_tab[1]) { + ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL); ++ if (!ctx->params.jpeg_qmat_tab[1]) ++ return -ENOMEM; ++ } + coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality); + } + +diff --git a/drivers/media/platform/chips-media/coda-jpeg.c b/drivers/media/platform/chips-media/coda-jpeg.c +index 435e7030fc2a8..ba8f410029172 100644 +--- a/drivers/media/platform/chips-media/coda-jpeg.c ++++ b/drivers/media/platform/chips-media/coda-jpeg.c +@@ -1052,10 +1052,16 @@ static int coda9_jpeg_start_encoding(struct coda_ctx *ctx) + v4l2_err(&dev->v4l2_dev, "error loading Huffman tables\n"); + return ret; + } +- if (!ctx->params.jpeg_qmat_tab[0]) ++ if (!ctx->params.jpeg_qmat_tab[0]) { + ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL); +- if (!ctx->params.jpeg_qmat_tab[1]) ++ if (!ctx->params.jpeg_qmat_tab[0]) ++ return -ENOMEM; ++ } ++ if (!ctx->params.jpeg_qmat_tab[1]) { + ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL); ++ if (!ctx->params.jpeg_qmat_tab[1]) ++ return -ENOMEM; ++ } + coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality); + + return 0; +diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-cmdq.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-cmdq.c +index 86c054600a08c..124c1b96e96bd 100644 +--- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-cmdq.c ++++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-cmdq.c +@@ -252,10 +252,9 @@ static int mdp_cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt *pkt, + dma_addr_t dma_addr; + + pkt->va_base = kzalloc(size, GFP_KERNEL); +- if (!pkt->va_base) { +- kfree(pkt); ++ if (!pkt->va_base) + return -ENOMEM; +- } ++ + pkt->buf_size = size; + pkt->cl = (void *)client; + +@@ -368,25 +367,30 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param) + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; +- goto err_cmdq_data; ++ goto err_cancel_job; + } + +- if (mdp_cmdq_pkt_create(mdp->cmdq_clt, &cmd->pkt, SZ_16K)) { +- ret = -ENOMEM; +- goto err_cmdq_data; +- } ++ ret = mdp_cmdq_pkt_create(mdp->cmdq_clt, &cmd->pkt, SZ_16K); ++ if (ret) ++ goto err_free_cmd; + + comps = kcalloc(param->config->num_components, sizeof(*comps), + GFP_KERNEL); + if (!comps) { + ret = -ENOMEM; +- goto err_cmdq_data; ++ goto err_destroy_pkt; + } + + path = kzalloc(sizeof(*path), GFP_KERNEL); + if (!path) { + ret = -ENOMEM; +- goto err_cmdq_data; ++ goto err_free_comps; ++ } ++ ++ ret = mtk_mutex_prepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]); ++ if (ret) { ++ dev_err(dev, "Fail to enable mutex clk\n"); ++ goto err_free_path; + } + + path->mdp_dev = mdp; +@@ -406,15 +410,13 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param) + ret = mdp_path_ctx_init(mdp, path); + if (ret) { + dev_err(dev, "mdp_path_ctx_init error\n"); +- goto err_cmdq_data; ++ goto err_free_path; + } + +- mtk_mutex_prepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]); +- + ret = mdp_path_config(mdp, cmd, path); + if (ret) { + dev_err(dev, "mdp_path_config error\n"); +- goto err_cmdq_data; ++ goto err_free_path; + } + cmdq_pkt_finalize(&cmd->pkt); + +@@ -431,10 +433,8 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param) + cmd->mdp_ctx = param->mdp_ctx; + + ret = mdp_comp_clocks_on(&mdp->pdev->dev, cmd->comps, cmd->num_comps); +- if (ret) { +- dev_err(dev, "comp %d failed to enable clock!\n", ret); +- goto err_clock_off; +- } ++ if (ret) ++ goto err_free_path; + + dma_sync_single_for_device(mdp->cmdq_clt->chan->mbox->dev, + cmd->pkt.pa_base, cmd->pkt.cmd_buf_size, +@@ -450,17 +450,20 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param) + return 0; + + err_clock_off: +- mtk_mutex_unprepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]); + mdp_comp_clocks_off(&mdp->pdev->dev, cmd->comps, + cmd->num_comps); +-err_cmdq_data: ++err_free_path: ++ mtk_mutex_unprepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]); + kfree(path); +- atomic_dec(&mdp->job_count); +- wake_up(&mdp->callback_wq); +- if (cmd && cmd->pkt.buf_size > 0) +- mdp_cmdq_pkt_destroy(&cmd->pkt); ++err_free_comps: + kfree(comps); ++err_destroy_pkt: ++ mdp_cmdq_pkt_destroy(&cmd->pkt); ++err_free_cmd: + kfree(cmd); ++err_cancel_job: ++ atomic_dec(&mdp->job_count); ++ + return ret; + } + EXPORT_SYMBOL_GPL(mdp_cmdq_send); +diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c +index d3eaf8884412d..7bc05f42a23c1 100644 +--- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c ++++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c +@@ -699,12 +699,22 @@ int mdp_comp_clock_on(struct device *dev, struct mdp_comp *comp) + dev_err(dev, + "Failed to enable clk %d. type:%d id:%d\n", + i, comp->type, comp->id); +- pm_runtime_put(comp->comp_dev); +- return ret; ++ goto err_revert; + } + } + + return 0; ++ ++err_revert: ++ while (--i >= 0) { ++ if (IS_ERR_OR_NULL(comp->clks[i])) ++ continue; ++ clk_disable_unprepare(comp->clks[i]); ++ } ++ if (comp->comp_dev) ++ pm_runtime_put_sync(comp->comp_dev); ++ ++ return ret; + } + + void mdp_comp_clock_off(struct device *dev, struct mdp_comp *comp) +@@ -723,11 +733,13 @@ void mdp_comp_clock_off(struct device *dev, struct mdp_comp *comp) + + int mdp_comp_clocks_on(struct device *dev, struct mdp_comp *comps, int num) + { +- int i; ++ int i, ret; + +- for (i = 0; i < num; i++) +- if (mdp_comp_clock_on(dev, &comps[i]) != 0) +- return ++i; ++ for (i = 0; i < num; i++) { ++ ret = mdp_comp_clock_on(dev, &comps[i]); ++ if (ret) ++ return ret; ++ } + + return 0; + } +diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c +index c413e59d42860..2d1f6ae9f0802 100644 +--- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c ++++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c +@@ -196,27 +196,27 @@ static int mdp_probe(struct platform_device *pdev) + mm_pdev = __get_pdev_by_id(pdev, MDP_INFRA_MMSYS); + if (!mm_pdev) { + ret = -ENODEV; +- goto err_return; ++ goto err_destroy_device; + } + mdp->mdp_mmsys = &mm_pdev->dev; + + mm_pdev = __get_pdev_by_id(pdev, MDP_INFRA_MUTEX); + if (WARN_ON(!mm_pdev)) { + ret = -ENODEV; +- goto err_return; ++ goto err_destroy_device; + } + for (i = 0; i < MDP_PIPE_MAX; i++) { + mdp->mdp_mutex[i] = mtk_mutex_get(&mm_pdev->dev); + if (!mdp->mdp_mutex[i]) { + ret = -ENODEV; +- goto err_return; ++ goto err_free_mutex; + } + } + + ret = mdp_comp_config(mdp); + if (ret) { + dev_err(dev, "Failed to config mdp components\n"); +- goto err_return; ++ goto err_free_mutex; + } + + mdp->job_wq = alloc_workqueue(MDP_MODULE_NAME, WQ_FREEZABLE, 0); +@@ -287,11 +287,12 @@ err_destroy_job_wq: + destroy_workqueue(mdp->job_wq); + err_deinit_comp: + mdp_comp_destroy(mdp); +-err_return: ++err_free_mutex: + for (i = 0; i < MDP_PIPE_MAX; i++) +- if (mdp) +- mtk_mutex_put(mdp->mdp_mutex[i]); ++ mtk_mutex_put(mdp->mdp_mutex[i]); ++err_destroy_device: + kfree(mdp); ++err_return: + dev_dbg(dev, "Errno %d\n", ret); + return ret; + } +diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c +index c45bd2599bb2d..ffbcee04dc26f 100644 +--- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c ++++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c +@@ -138,10 +138,13 @@ static void mtk_vdec_stateless_cap_to_disp(struct mtk_vcodec_ctx *ctx, int error + state = VB2_BUF_STATE_DONE; + + vb2_dst = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); +- v4l2_m2m_buf_done(vb2_dst, state); +- +- mtk_v4l2_debug(2, "free frame buffer id:%d to done list", +- vb2_dst->vb2_buf.index); ++ if (vb2_dst) { ++ v4l2_m2m_buf_done(vb2_dst, state); ++ mtk_v4l2_debug(2, "free frame buffer id:%d to done list", ++ vb2_dst->vb2_buf.index); ++ } else { ++ mtk_v4l2_err("dst buffer is NULL"); ++ } + + if (src_buf_req) + v4l2_ctrl_request_complete(src_buf_req, &ctx->ctrl_hdl); +@@ -250,7 +253,7 @@ static void mtk_vdec_worker(struct work_struct *work) + + state = ret ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE; + if (!IS_VDEC_LAT_ARCH(dev->vdec_pdata->hw_arch) || +- ctx->current_codec == V4L2_PIX_FMT_VP8_FRAME || ret) { ++ ctx->current_codec == V4L2_PIX_FMT_VP8_FRAME) { + v4l2_m2m_buf_done_and_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx, state); + if (src_buf_req) + v4l2_ctrl_request_complete(src_buf_req, &ctx->ctrl_hdl); +diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c +index 4cc92700692b3..955b2d0c8f53f 100644 +--- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c ++++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c +@@ -471,14 +471,19 @@ static int vdec_h264_slice_core_decode(struct vdec_lat_buf *lat_buf) + sizeof(share_info->h264_slice_params)); + + fb = ctx->dev->vdec_pdata->get_cap_buffer(ctx); +- y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0; +- vdec_fb_va = (unsigned long)fb; ++ if (!fb) { ++ err = -EBUSY; ++ mtk_vcodec_err(inst, "fb buffer is NULL"); ++ goto vdec_dec_end; ++ } + ++ vdec_fb_va = (unsigned long)fb; ++ y_fb_dma = (u64)fb->base_y.dma_addr; + if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 1) + c_fb_dma = + y_fb_dma + inst->ctx->picinfo.buf_w * inst->ctx->picinfo.buf_h; + else +- c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0; ++ c_fb_dma = (u64)fb->base_c.dma_addr; + + mtk_vcodec_debug(inst, "[h264-core] y/c addr = 0x%llx 0x%llx", y_fb_dma, + c_fb_dma); +@@ -539,6 +544,29 @@ vdec_dec_end: + return 0; + } + ++static void vdec_h264_insert_startcode(struct mtk_vcodec_dev *vcodec_dev, unsigned char *buf, ++ size_t *bs_size, struct mtk_h264_pps_param *pps) ++{ ++ struct device *dev = &vcodec_dev->plat_dev->dev; ++ ++ /* Need to add pending data at the end of bitstream when bs_sz is small than ++ * 20 bytes for cavlc bitstream, or lat will decode fail. This pending data is ++ * useful for mt8192 and mt8195 platform. ++ * ++ * cavlc bitstream when entropy_coding_mode_flag is false. ++ */ ++ if (pps->entropy_coding_mode_flag || *bs_size > 20 || ++ !(of_device_is_compatible(dev->of_node, "mediatek,mt8192-vcodec-dec") || ++ of_device_is_compatible(dev->of_node, "mediatek,mt8195-vcodec-dec"))) ++ return; ++ ++ buf[*bs_size] = 0; ++ buf[*bs_size + 1] = 0; ++ buf[*bs_size + 2] = 1; ++ buf[*bs_size + 3] = 0xff; ++ (*bs_size) += 4; ++} ++ + static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, + struct vdec_fb *fb, bool *res_chg) + { +@@ -582,9 +610,6 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, + } + + inst->vsi->dec.nal_info = buf[nal_start_idx]; +- inst->vsi->dec.bs_buf_addr = (u64)bs->dma_addr; +- inst->vsi->dec.bs_buf_size = bs->size; +- + lat_buf->src_buf_req = src_buf_info->m2m_buf.vb.vb2_buf.req_obj.req; + v4l2_m2m_buf_copy_metadata(&src_buf_info->m2m_buf.vb, &lat_buf->ts_info, true); + +@@ -592,6 +617,12 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, + if (err) + goto err_free_fb_out; + ++ vdec_h264_insert_startcode(inst->ctx->dev, buf, &bs->size, ++ &share_info->h264_slice_params.pps); ++ ++ inst->vsi->dec.bs_buf_addr = (uint64_t)bs->dma_addr; ++ inst->vsi->dec.bs_buf_size = bs->size; ++ + *res_chg = inst->resolution_changed; + if (inst->resolution_changed) { + mtk_vcodec_debug(inst, "- resolution changed -"); +@@ -630,7 +661,7 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, + err = vpu_dec_start(vpu, data, 2); + if (err) { + mtk_vcodec_debug(inst, "lat decode err: %d", err); +- goto err_scp_decode; ++ goto err_free_fb_out; + } + + share_info->trans_end = inst->ctx->msg_queue.wdma_addr.dma_addr + +@@ -647,12 +678,17 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, + /* wait decoder done interrupt */ + timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED, + WAIT_INTR_TIMEOUT_MS, MTK_VDEC_LAT0); ++ if (timeout) ++ mtk_vcodec_err(inst, "lat decode timeout: pic_%d", inst->slice_dec_num); + inst->vsi->dec.timeout = !!timeout; + + err = vpu_dec_end(vpu); +- if (err == SLICE_HEADER_FULL || timeout || err == TRANS_BUFFER_FULL) { +- err = -EINVAL; +- goto err_scp_decode; ++ if (err == SLICE_HEADER_FULL || err == TRANS_BUFFER_FULL) { ++ if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) ++ vdec_msg_queue_qbuf(&inst->ctx->msg_queue.lat_ctx, lat_buf); ++ inst->slice_dec_num++; ++ mtk_vcodec_err(inst, "lat dec fail: pic_%d err:%d", inst->slice_dec_num, err); ++ return -EINVAL; + } + + share_info->trans_end = inst->ctx->msg_queue.wdma_addr.dma_addr + +@@ -669,10 +705,6 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, + + inst->slice_dec_num++; + return 0; +- +-err_scp_decode: +- if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) +- vdec_msg_queue_qbuf(&inst->ctx->msg_queue.lat_ctx, lat_buf); + err_free_fb_out: + vdec_msg_queue_qbuf(&inst->ctx->msg_queue.lat_ctx, lat_buf); + mtk_vcodec_err(inst, "slice dec number: %d err: %d", inst->slice_dec_num, err); +diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c +index fb1c36a3592d1..cbb6728b8a40b 100644 +--- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c ++++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c +@@ -2073,21 +2073,23 @@ static int vdec_vp9_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, + return -EBUSY; + } + pfc = (struct vdec_vp9_slice_pfc *)lat_buf->private_data; +- if (!pfc) +- return -EINVAL; ++ if (!pfc) { ++ ret = -EINVAL; ++ goto err_free_fb_out; ++ } + vsi = &pfc->vsi; + + ret = vdec_vp9_slice_setup_lat(instance, bs, lat_buf, pfc); + if (ret) { + mtk_vcodec_err(instance, "Failed to setup VP9 lat ret %d\n", ret); +- return ret; ++ goto err_free_fb_out; + } + vdec_vp9_slice_vsi_to_remote(vsi, instance->vsi); + + ret = vpu_dec_start(&instance->vpu, NULL, 0); + if (ret) { + mtk_vcodec_err(instance, "Failed to dec VP9 ret %d\n", ret); +- return ret; ++ goto err_free_fb_out; + } + + if (instance->irq) { +@@ -2107,7 +2109,7 @@ static int vdec_vp9_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, + /* LAT trans full, no more UBE or decode timeout */ + if (ret) { + mtk_vcodec_err(instance, "VP9 decode error: %d\n", ret); +- return ret; ++ goto err_free_fb_out; + } + + mtk_vcodec_debug(instance, "lat dma addr: 0x%lx 0x%lx\n", +@@ -2120,6 +2122,9 @@ static int vdec_vp9_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, + vdec_msg_queue_qbuf(&ctx->dev->msg_queue_core_ctx, lat_buf); + + return 0; ++err_free_fb_out: ++ vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf); ++ return ret; + } + + static int vdec_vp9_slice_decode(void *h_vdec, struct mtk_vcodec_mem *bs, +diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c +index ae500980ad45c..dc2004790a472 100644 +--- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c ++++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c +@@ -221,7 +221,7 @@ static void vdec_msg_queue_core_work(struct work_struct *work) + mtk_vcodec_dec_disable_hardware(ctx, MTK_VDEC_CORE); + vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf); + +- if (!list_empty(&ctx->msg_queue.lat_ctx.ready_queue)) { ++ if (!list_empty(&dev->msg_queue_core_ctx.ready_queue)) { + mtk_v4l2_debug(3, "re-schedule to decode for core: %d", + dev->msg_queue_core_ctx.ready_num); + queue_work(dev->core_workqueue, &msg_queue->core_work); +diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.c +index 9418fcf740a82..ef28122a5ed49 100644 +--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.c ++++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.c +@@ -76,12 +76,14 @@ void print_wrapper_info(struct device *dev, void __iomem *reg) + + void mxc_jpeg_enable_irq(void __iomem *reg, int slot) + { +- writel(0xFFFFFFFF, reg + MXC_SLOT_OFFSET(slot, SLOT_IRQ_EN)); ++ writel(0xFFFFFFFF, reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS)); ++ writel(0xF0C, reg + MXC_SLOT_OFFSET(slot, SLOT_IRQ_EN)); + } + + void mxc_jpeg_disable_irq(void __iomem *reg, int slot) + { + writel(0x0, reg + MXC_SLOT_OFFSET(slot, SLOT_IRQ_EN)); ++ writel(0xFFFFFFFF, reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS)); + } + + void mxc_jpeg_sw_reset(void __iomem *reg) +diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c +index 81fb3a5bc1d51..41deda232e4a1 100644 +--- a/drivers/media/platform/qcom/camss/camss-video.c ++++ b/drivers/media/platform/qcom/camss/camss-video.c +@@ -495,7 +495,7 @@ static int video_start_streaming(struct vb2_queue *q, unsigned int count) + + ret = video_device_pipeline_start(vdev, &video->pipe); + if (ret < 0) +- return ret; ++ goto flush_buffers; + + ret = video_check_format(video); + if (ret < 0) +@@ -524,6 +524,7 @@ static int video_start_streaming(struct vb2_queue *q, unsigned int count) + error: + video_device_pipeline_stop(vdev); + ++flush_buffers: + video->ops->flush_buffers(video, VB2_BUF_STATE_QUEUED); + + return ret; +diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c +index 1118c40886d52..a157cac72e0ab 100644 +--- a/drivers/media/platform/qcom/camss/camss.c ++++ b/drivers/media/platform/qcom/camss/camss.c +@@ -1465,6 +1465,14 @@ static int camss_configure_pd(struct camss *camss) + return camss->genpd_num; + } + ++ /* ++ * If a platform device has just one power domain, then it is attached ++ * at platform_probe() level, thus there shall be no need and even no ++ * option to attach it again, this is the case for CAMSS on MSM8916. ++ */ ++ if (camss->genpd_num == 1) ++ return 0; ++ + camss->genpd = devm_kmalloc_array(dev, camss->genpd_num, + sizeof(*camss->genpd), GFP_KERNEL); + if (!camss->genpd) +@@ -1698,6 +1706,9 @@ void camss_delete(struct camss *camss) + + pm_runtime_disable(camss->dev); + ++ if (camss->genpd_num == 1) ++ return; ++ + for (i = 0; i < camss->genpd_num; i++) { + device_link_del(camss->genpd_link[i]); + dev_pm_domain_detach(camss->genpd[i], true); +diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c +index c93d2906e4c7d..48c9084bb4dba 100644 +--- a/drivers/media/platform/qcom/venus/pm_helpers.c ++++ b/drivers/media/platform/qcom/venus/pm_helpers.c +@@ -869,8 +869,8 @@ static int vcodec_domains_get(struct venus_core *core) + for (i = 0; i < res->vcodec_pmdomains_num; i++) { + pd = dev_pm_domain_attach_by_name(dev, + res->vcodec_pmdomains[i]); +- if (IS_ERR(pd)) +- return PTR_ERR(pd); ++ if (IS_ERR_OR_NULL(pd)) ++ return PTR_ERR(pd) ? : -ENODATA; + core->pmdomains[i] = pd; + } + +diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-core.c b/drivers/media/platform/samsung/exynos4-is/fimc-core.c +index 91cc8d58a663b..1791100b69353 100644 +--- a/drivers/media/platform/samsung/exynos4-is/fimc-core.c ++++ b/drivers/media/platform/samsung/exynos4-is/fimc-core.c +@@ -1173,7 +1173,7 @@ int __init fimc_register_driver(void) + return platform_driver_register(&fimc_driver); + } + +-void __exit fimc_unregister_driver(void) ++void fimc_unregister_driver(void) + { + platform_driver_unregister(&fimc_driver); + } +diff --git a/drivers/media/platform/samsung/exynos4-is/media-dev.c b/drivers/media/platform/samsung/exynos4-is/media-dev.c +index 52b43ea040302..2f3071acb9c97 100644 +--- a/drivers/media/platform/samsung/exynos4-is/media-dev.c ++++ b/drivers/media/platform/samsung/exynos4-is/media-dev.c +@@ -1380,9 +1380,7 @@ static int subdev_notifier_bound(struct v4l2_async_notifier *notifier, + + /* Find platform data for this sensor subdev */ + for (i = 0; i < ARRAY_SIZE(fmd->sensor); i++) +- if (fmd->sensor[i].asd && +- fmd->sensor[i].asd->match.fwnode == +- of_fwnode_handle(subdev->dev->of_node)) ++ if (fmd->sensor[i].asd == asd) + si = &fmd->sensor[i]; + + if (si == NULL) +@@ -1474,7 +1472,7 @@ static int fimc_md_probe(struct platform_device *pdev) + pinctrl = devm_pinctrl_get(dev); + if (IS_ERR(pinctrl)) { + ret = PTR_ERR(pinctrl); +- if (ret != EPROBE_DEFER) ++ if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to get pinctrl: %d\n", ret); + goto err_clk; + } +@@ -1586,7 +1584,11 @@ static int __init fimc_md_init(void) + if (ret) + return ret; + +- return platform_driver_register(&fimc_md_driver); ++ ret = platform_driver_register(&fimc_md_driver); ++ if (ret) ++ fimc_unregister_driver(); ++ ++ return ret; + } + + static void __exit fimc_md_exit(void) +diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c +index fca5c6405eec3..007c7dbee0377 100644 +--- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c ++++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c +@@ -1576,8 +1576,18 @@ static struct s5p_mfc_variant mfc_drvdata_v7 = { + .port_num = MFC_NUM_PORTS_V7, + .buf_size = &buf_size_v7, + .fw_name[0] = "s5p-mfc-v7.fw", +- .clk_names = {"mfc", "sclk_mfc"}, +- .num_clocks = 2, ++ .clk_names = {"mfc"}, ++ .num_clocks = 1, ++}; ++ ++static struct s5p_mfc_variant mfc_drvdata_v7_3250 = { ++ .version = MFC_VERSION_V7, ++ .version_bit = MFC_V7_BIT, ++ .port_num = MFC_NUM_PORTS_V7, ++ .buf_size = &buf_size_v7, ++ .fw_name[0] = "s5p-mfc-v7.fw", ++ .clk_names = {"mfc", "sclk_mfc"}, ++ .num_clocks = 2, + }; + + static struct s5p_mfc_buf_size_v6 mfc_buf_size_v8 = { +@@ -1647,6 +1657,9 @@ static const struct of_device_id exynos_mfc_match[] = { + }, { + .compatible = "samsung,mfc-v7", + .data = &mfc_drvdata_v7, ++ }, { ++ .compatible = "samsung,exynos3250-mfc", ++ .data = &mfc_drvdata_v7_3250, + }, { + .compatible = "samsung,mfc-v8", + .data = &mfc_drvdata_v8, +diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c +index cefe6b7bfdc4e..1dbb89f0ddb8c 100644 +--- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c ++++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c +@@ -925,6 +925,7 @@ static int configure_channels(struct c8sectpfei *fei) + if (ret) { + dev_err(fei->dev, + "configure_memdma_and_inputblock failed\n"); ++ of_node_put(child); + goto err_unmap; + } + index++; +diff --git a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c +index 30d6c0c5161f4..484ac5f054d53 100644 +--- a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c ++++ b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c +@@ -498,6 +498,7 @@ static int sun6i_mipi_csi2_bridge_setup(struct sun6i_mipi_csi2_device *csi2_dev) + struct v4l2_async_notifier *notifier = &bridge->notifier; + struct media_pad *pads = bridge->pads; + struct device *dev = csi2_dev->dev; ++ bool notifier_registered = false; + int ret; + + mutex_init(&bridge->lock); +@@ -519,8 +520,10 @@ static int sun6i_mipi_csi2_bridge_setup(struct sun6i_mipi_csi2_device *csi2_dev) + + /* Media Pads */ + +- pads[SUN6I_MIPI_CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK; +- pads[SUN6I_MIPI_CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; ++ pads[SUN6I_MIPI_CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK | ++ MEDIA_PAD_FL_MUST_CONNECT; ++ pads[SUN6I_MIPI_CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE | ++ MEDIA_PAD_FL_MUST_CONNECT; + + ret = media_entity_pads_init(&subdev->entity, SUN6I_MIPI_CSI2_PAD_COUNT, + pads); +@@ -533,12 +536,17 @@ static int sun6i_mipi_csi2_bridge_setup(struct sun6i_mipi_csi2_device *csi2_dev) + notifier->ops = &sun6i_mipi_csi2_notifier_ops; + + ret = sun6i_mipi_csi2_bridge_source_setup(csi2_dev); +- if (ret) ++ if (ret && ret != -ENODEV) + goto error_v4l2_notifier_cleanup; + +- ret = v4l2_async_subdev_nf_register(subdev, notifier); +- if (ret < 0) +- goto error_v4l2_notifier_cleanup; ++ /* Only register the notifier when a sensor is connected. */ ++ if (ret != -ENODEV) { ++ ret = v4l2_async_subdev_nf_register(subdev, notifier); ++ if (ret < 0) ++ goto error_v4l2_notifier_cleanup; ++ ++ notifier_registered = true; ++ } + + /* V4L2 Subdev */ + +@@ -549,7 +557,8 @@ static int sun6i_mipi_csi2_bridge_setup(struct sun6i_mipi_csi2_device *csi2_dev) + return 0; + + error_v4l2_notifier_unregister: +- v4l2_async_nf_unregister(notifier); ++ if (notifier_registered) ++ v4l2_async_nf_unregister(notifier); + + error_v4l2_notifier_cleanup: + v4l2_async_nf_cleanup(notifier); +diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c +index b032ec13a683a..d993c09a48202 100644 +--- a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c ++++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c +@@ -536,6 +536,7 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev) + struct v4l2_async_notifier *notifier = &bridge->notifier; + struct media_pad *pads = bridge->pads; + struct device *dev = csi2_dev->dev; ++ bool notifier_registered = false; + int ret; + + mutex_init(&bridge->lock); +@@ -557,8 +558,10 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev) + + /* Media Pads */ + +- pads[SUN8I_A83T_MIPI_CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK; +- pads[SUN8I_A83T_MIPI_CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; ++ pads[SUN8I_A83T_MIPI_CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK | ++ MEDIA_PAD_FL_MUST_CONNECT; ++ pads[SUN8I_A83T_MIPI_CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE | ++ MEDIA_PAD_FL_MUST_CONNECT; + + ret = media_entity_pads_init(&subdev->entity, + SUN8I_A83T_MIPI_CSI2_PAD_COUNT, pads); +@@ -571,12 +574,17 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev) + notifier->ops = &sun8i_a83t_mipi_csi2_notifier_ops; + + ret = sun8i_a83t_mipi_csi2_bridge_source_setup(csi2_dev); +- if (ret) ++ if (ret && ret != -ENODEV) + goto error_v4l2_notifier_cleanup; + +- ret = v4l2_async_subdev_nf_register(subdev, notifier); +- if (ret < 0) +- goto error_v4l2_notifier_cleanup; ++ /* Only register the notifier when a sensor is connected. */ ++ if (ret != -ENODEV) { ++ ret = v4l2_async_subdev_nf_register(subdev, notifier); ++ if (ret < 0) ++ goto error_v4l2_notifier_cleanup; ++ ++ notifier_registered = true; ++ } + + /* V4L2 Subdev */ + +@@ -587,7 +595,8 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev) + return 0; + + error_v4l2_notifier_unregister: +- v4l2_async_nf_unregister(notifier); ++ if (notifier_registered) ++ v4l2_async_nf_unregister(notifier); + + error_v4l2_notifier_cleanup: + v4l2_async_nf_cleanup(notifier); +diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c +index 6b2768623c883..aa7a580dbecc0 100644 +--- a/drivers/media/radio/si470x/radio-si470x-usb.c ++++ b/drivers/media/radio/si470x/radio-si470x-usb.c +@@ -727,8 +727,10 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, + + /* start radio */ + retval = si470x_start_usb(radio); +- if (retval < 0) ++ if (retval < 0 && !radio->int_in_running) + goto err_buf; ++ else if (retval < 0) /* in case of radio->int_in_running == 1 */ ++ goto err_all; + + /* set initial frequency */ + si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ +diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c +index 5edfd8a9e8494..74546f7e34691 100644 +--- a/drivers/media/rc/imon.c ++++ b/drivers/media/rc/imon.c +@@ -646,15 +646,14 @@ static int send_packet(struct imon_context *ictx) + pr_err_ratelimited("error submitting urb(%d)\n", retval); + } else { + /* Wait for transmission to complete (or abort) */ +- mutex_unlock(&ictx->lock); + retval = wait_for_completion_interruptible( + &ictx->tx.finished); + if (retval) { + usb_kill_urb(ictx->tx_urb); + pr_err_ratelimited("task interrupted\n"); + } +- mutex_lock(&ictx->lock); + ++ ictx->tx.busy = false; + retval = ictx->tx.status; + if (retval) + pr_err_ratelimited("packet tx failed (%d)\n", retval); +@@ -953,7 +952,8 @@ static ssize_t vfd_write(struct file *file, const char __user *buf, + if (ictx->disconnected) + return -ENODEV; + +- mutex_lock(&ictx->lock); ++ if (mutex_lock_interruptible(&ictx->lock)) ++ return -ERESTARTSYS; + + if (!ictx->dev_present_intf0) { + pr_err_ratelimited("no iMON device present\n"); +diff --git a/drivers/media/test-drivers/vidtv/vidtv_bridge.c b/drivers/media/test-drivers/vidtv/vidtv_bridge.c +index 82620613d56b8..dff7265a42ca2 100644 +--- a/drivers/media/test-drivers/vidtv/vidtv_bridge.c ++++ b/drivers/media/test-drivers/vidtv/vidtv_bridge.c +@@ -459,26 +459,20 @@ fail_dmx_conn: + for (j = j - 1; j >= 0; --j) + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, + &dvb->dmx_fe[j]); +-fail_dmx_dev: + dvb_dmxdev_release(&dvb->dmx_dev); +-fail_dmx: ++fail_dmx_dev: + dvb_dmx_release(&dvb->demux); ++fail_dmx: ++fail_demod_probe: ++ for (i = i - 1; i >= 0; --i) { ++ dvb_unregister_frontend(dvb->fe[i]); + fail_fe: +- for (j = i; j >= 0; --j) +- dvb_unregister_frontend(dvb->fe[j]); ++ dvb_module_release(dvb->i2c_client_tuner[i]); + fail_tuner_probe: +- for (j = i; j >= 0; --j) +- if (dvb->i2c_client_tuner[j]) +- dvb_module_release(dvb->i2c_client_tuner[j]); +- +-fail_demod_probe: +- for (j = i; j >= 0; --j) +- if (dvb->i2c_client_demod[j]) +- dvb_module_release(dvb->i2c_client_demod[j]); +- ++ dvb_module_release(dvb->i2c_client_demod[i]); ++ } + fail_adapter: + dvb_unregister_adapter(&dvb->adapter); +- + fail_i2c: + i2c_del_adapter(&dvb->i2c_adapter); + +diff --git a/drivers/media/test-drivers/vimc/vimc-core.c b/drivers/media/test-drivers/vimc/vimc-core.c +index 2ae7a0f11ebfc..e82cfa5ffbf47 100644 +--- a/drivers/media/test-drivers/vimc/vimc-core.c ++++ b/drivers/media/test-drivers/vimc/vimc-core.c +@@ -433,7 +433,7 @@ static int __init vimc_init(void) + if (ret) { + dev_err(&vimc_pdev.dev, + "platform driver registration failed (err=%d)\n", ret); +- platform_driver_unregister(&vimc_pdrv); ++ platform_device_unregister(&vimc_pdev); + return ret; + } + +diff --git a/drivers/media/test-drivers/vivid/vivid-vid-cap.c b/drivers/media/test-drivers/vivid/vivid-vid-cap.c +index 11620eaf941e3..c0999581c599b 100644 +--- a/drivers/media/test-drivers/vivid/vivid-vid-cap.c ++++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.c +@@ -973,6 +973,7 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection + if (dev->has_compose_cap) { + v4l2_rect_set_min_size(compose, &min_rect); + v4l2_rect_set_max_size(compose, &max_rect); ++ v4l2_rect_map_inside(compose, &fmt); + } + dev->fmt_cap_rect = fmt; + tpg_s_buf_height(&dev->tpg, fmt.height); +diff --git a/drivers/media/usb/dvb-usb/az6027.c b/drivers/media/usb/dvb-usb/az6027.c +index cf15988dfb510..7d78ee09be5e1 100644 +--- a/drivers/media/usb/dvb-usb/az6027.c ++++ b/drivers/media/usb/dvb-usb/az6027.c +@@ -975,6 +975,10 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n + if (msg[i].addr == 0x99) { + req = 0xBE; + index = 0; ++ if (msg[i].len < 1) { ++ i = -EOPNOTSUPP; ++ break; ++ } + value = msg[i].buf[0] & 0x00ff; + length = 1; + az6027_usb_out_op(d, req, value, index, data, length); +diff --git a/drivers/media/usb/dvb-usb/dvb-usb-init.c b/drivers/media/usb/dvb-usb/dvb-usb-init.c +index 61439c8f33cab..58eea8ab54779 100644 +--- a/drivers/media/usb/dvb-usb/dvb-usb-init.c ++++ b/drivers/media/usb/dvb-usb/dvb-usb-init.c +@@ -81,7 +81,7 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs) + + ret = dvb_usb_adapter_stream_init(adap); + if (ret) +- return ret; ++ goto stream_init_err; + + ret = dvb_usb_adapter_dvb_init(adap, adapter_nrs); + if (ret) +@@ -114,6 +114,8 @@ frontend_init_err: + dvb_usb_adapter_dvb_exit(adap); + dvb_init_err: + dvb_usb_adapter_stream_exit(adap); ++stream_init_err: ++ kfree(adap->priv); + return ret; + } + +diff --git a/drivers/media/v4l2-core/v4l2-ctrls-api.c b/drivers/media/v4l2-core/v4l2-ctrls-api.c +index d0a3aa3806fbd..3d3b6dc24ca63 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls-api.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls-api.c +@@ -150,6 +150,7 @@ static int user_to_new(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl) + * then return an error. + */ + if (strlen(ctrl->p_new.p_char) == ctrl->maximum && last) ++ ctrl->is_new = 1; + return -ERANGE; + } + return ret; +diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c +index 0dab1d7b90f0e..29169170880a6 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls-core.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c +@@ -1827,7 +1827,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, + else if (type == V4L2_CTRL_TYPE_INTEGER_MENU) + qmenu_int = v4l2_ctrl_get_int_menu(id, &qmenu_int_len); + +- if ((!qmenu && !qmenu_int) || (qmenu_int && max > qmenu_int_len)) { ++ if ((!qmenu && !qmenu_int) || (qmenu_int && max >= qmenu_int_len)) { + handler_set_err(hdl, -EINVAL); + return NULL; + } +diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c +index fddba75d90745..6876ec25bc512 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -1347,23 +1347,23 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) + case V4L2_PIX_FMT_YUV420: descr = "Planar YUV 4:2:0"; break; + case V4L2_PIX_FMT_HI240: descr = "8-bit Dithered RGB (BTTV)"; break; + case V4L2_PIX_FMT_M420: descr = "YUV 4:2:0 (M420)"; break; +- case V4L2_PIX_FMT_NV12: descr = "Y/CbCr 4:2:0"; break; +- case V4L2_PIX_FMT_NV21: descr = "Y/CrCb 4:2:0"; break; +- case V4L2_PIX_FMT_NV16: descr = "Y/CbCr 4:2:2"; break; +- case V4L2_PIX_FMT_NV61: descr = "Y/CrCb 4:2:2"; break; +- case V4L2_PIX_FMT_NV24: descr = "Y/CbCr 4:4:4"; break; +- case V4L2_PIX_FMT_NV42: descr = "Y/CrCb 4:4:4"; break; +- case V4L2_PIX_FMT_P010: descr = "10-bit Y/CbCr 4:2:0"; break; +- case V4L2_PIX_FMT_NV12_4L4: descr = "Y/CbCr 4:2:0 (4x4 Linear)"; break; +- case V4L2_PIX_FMT_NV12_16L16: descr = "Y/CbCr 4:2:0 (16x16 Linear)"; break; +- case V4L2_PIX_FMT_NV12_32L32: descr = "Y/CbCr 4:2:0 (32x32 Linear)"; break; +- case V4L2_PIX_FMT_P010_4L4: descr = "10-bit Y/CbCr 4:2:0 (4x4 Linear)"; break; +- case V4L2_PIX_FMT_NV12M: descr = "Y/CbCr 4:2:0 (N-C)"; break; +- case V4L2_PIX_FMT_NV21M: descr = "Y/CrCb 4:2:0 (N-C)"; break; +- case V4L2_PIX_FMT_NV16M: descr = "Y/CbCr 4:2:2 (N-C)"; break; +- case V4L2_PIX_FMT_NV61M: descr = "Y/CrCb 4:2:2 (N-C)"; break; +- case V4L2_PIX_FMT_NV12MT: descr = "Y/CbCr 4:2:0 (64x32 MB, N-C)"; break; +- case V4L2_PIX_FMT_NV12MT_16X16: descr = "Y/CbCr 4:2:0 (16x16 MB, N-C)"; break; ++ case V4L2_PIX_FMT_NV12: descr = "Y/UV 4:2:0"; break; ++ case V4L2_PIX_FMT_NV21: descr = "Y/VU 4:2:0"; break; ++ case V4L2_PIX_FMT_NV16: descr = "Y/UV 4:2:2"; break; ++ case V4L2_PIX_FMT_NV61: descr = "Y/VU 4:2:2"; break; ++ case V4L2_PIX_FMT_NV24: descr = "Y/UV 4:4:4"; break; ++ case V4L2_PIX_FMT_NV42: descr = "Y/VU 4:4:4"; break; ++ case V4L2_PIX_FMT_P010: descr = "10-bit Y/UV 4:2:0"; break; ++ case V4L2_PIX_FMT_NV12_4L4: descr = "Y/UV 4:2:0 (4x4 Linear)"; break; ++ case V4L2_PIX_FMT_NV12_16L16: descr = "Y/UV 4:2:0 (16x16 Linear)"; break; ++ case V4L2_PIX_FMT_NV12_32L32: descr = "Y/UV 4:2:0 (32x32 Linear)"; break; ++ case V4L2_PIX_FMT_P010_4L4: descr = "10-bit Y/UV 4:2:0 (4x4 Linear)"; break; ++ case V4L2_PIX_FMT_NV12M: descr = "Y/UV 4:2:0 (N-C)"; break; ++ case V4L2_PIX_FMT_NV21M: descr = "Y/VU 4:2:0 (N-C)"; break; ++ case V4L2_PIX_FMT_NV16M: descr = "Y/UV 4:2:2 (N-C)"; break; ++ case V4L2_PIX_FMT_NV61M: descr = "Y/VU 4:2:2 (N-C)"; break; ++ case V4L2_PIX_FMT_NV12MT: descr = "Y/UV 4:2:0 (64x32 MB, N-C)"; break; ++ case V4L2_PIX_FMT_NV12MT_16X16: descr = "Y/UV 4:2:0 (16x16 MB, N-C)"; break; + case V4L2_PIX_FMT_YUV420M: descr = "Planar YUV 4:2:0 (N-C)"; break; + case V4L2_PIX_FMT_YVU420M: descr = "Planar YVU 4:2:0 (N-C)"; break; + case V4L2_PIX_FMT_YUV422M: descr = "Planar YUV 4:2:2 (N-C)"; break; +diff --git a/drivers/media/v4l2-core/videobuf-dma-contig.c b/drivers/media/v4l2-core/videobuf-dma-contig.c +index 52312ce2ba056..f2c4393595574 100644 +--- a/drivers/media/v4l2-core/videobuf-dma-contig.c ++++ b/drivers/media/v4l2-core/videobuf-dma-contig.c +@@ -36,12 +36,11 @@ struct videobuf_dma_contig_memory { + + static int __videobuf_dc_alloc(struct device *dev, + struct videobuf_dma_contig_memory *mem, +- unsigned long size, gfp_t flags) ++ unsigned long size) + { + mem->size = size; +- mem->vaddr = dma_alloc_coherent(dev, mem->size, +- &mem->dma_handle, flags); +- ++ mem->vaddr = dma_alloc_coherent(dev, mem->size, &mem->dma_handle, ++ GFP_KERNEL); + if (!mem->vaddr) { + dev_err(dev, "memory alloc size %ld failed\n", mem->size); + return -ENOMEM; +@@ -258,8 +257,7 @@ static int __videobuf_iolock(struct videobuf_queue *q, + return videobuf_dma_contig_user_get(mem, vb); + + /* allocate memory for the read() method */ +- if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(vb->size), +- GFP_KERNEL)) ++ if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(vb->size))) + return -ENOMEM; + break; + case V4L2_MEMORY_OVERLAY: +@@ -295,22 +293,18 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, + BUG_ON(!mem); + MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); + +- if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(buf->bsize), +- GFP_KERNEL | __GFP_COMP)) ++ if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(buf->bsize))) + goto error; + +- /* Try to remap memory */ +- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); +- + /* the "vm_pgoff" is just used in v4l2 to find the + * corresponding buffer data structure which is allocated + * earlier and it does not mean the offset from the physical + * buffer start address as usual. So set it to 0 to pass +- * the sanity check in vm_iomap_memory(). ++ * the sanity check in dma_mmap_coherent(). + */ + vma->vm_pgoff = 0; +- +- retval = vm_iomap_memory(vma, mem->dma_handle, mem->size); ++ retval = dma_mmap_coherent(q->dev, vma, mem->vaddr, mem->dma_handle, ++ mem->size); + if (retval) { + dev_err(q->dev, "mmap: remap failed with error %d. ", + retval); +diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c +index 4316988d791a5..61c288d403750 100644 +--- a/drivers/memory/renesas-rpc-if.c ++++ b/drivers/memory/renesas-rpc-if.c +@@ -317,6 +317,9 @@ int rpcif_hw_init(struct rpcif *rpc, bool hyperflash) + regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_PHYMEM_MASK, + RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0)); + ++ /* DMA Transfer is not supported */ ++ regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_HS, 0); ++ + if (rpc->type == RPCIF_RCAR_GEN3) + regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, + RPCIF_PHYCNT_STRTIM(7), RPCIF_PHYCNT_STRTIM(7)); +diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c +index ba84145195158..04115cd92433b 100644 +--- a/drivers/memstick/core/ms_block.c ++++ b/drivers/memstick/core/ms_block.c +@@ -2116,6 +2116,11 @@ static int msb_init_disk(struct memstick_dev *card) + dbg("Set total disk size to %lu sectors", capacity); + + msb->io_queue = alloc_ordered_workqueue("ms_block", WQ_MEM_RECLAIM); ++ if (!msb->io_queue) { ++ rc = -ENOMEM; ++ goto out_cleanup_disk; ++ } ++ + INIT_WORK(&msb->io_work, msb_io_work); + sg_init_table(msb->prealloc_sg, MS_BLOCK_MAX_SEGS+1); + +@@ -2125,10 +2130,12 @@ static int msb_init_disk(struct memstick_dev *card) + msb_start(card); + rc = device_add_disk(&card->dev, msb->disk, NULL); + if (rc) +- goto out_cleanup_disk; ++ goto out_destroy_workqueue; + dbg("Disk added"); + return 0; + ++out_destroy_workqueue: ++ destroy_workqueue(msb->io_queue); + out_cleanup_disk: + put_disk(msb->disk); + out_free_tag_set: +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index 8b93856de432a..9940e2724c05d 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -2027,6 +2027,7 @@ config MFD_ROHM_BD957XMUF + depends on I2C=y + depends on OF + select REGMAP_I2C ++ select REGMAP_IRQ + select MFD_CORE + help + Select this option to get support for the ROHM BD9576MUF and +diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c +index 88a212a8168cf..880c41fa7021b 100644 +--- a/drivers/mfd/axp20x.c ++++ b/drivers/mfd/axp20x.c +@@ -842,7 +842,7 @@ static void axp20x_power_off(void) + AXP20X_OFF); + + /* Give capacitors etc. time to drain to avoid kernel panic msg. */ +- msleep(500); ++ mdelay(500); + } + + int axp20x_match_device(struct axp20x_dev *axp20x) +diff --git a/drivers/mfd/mt6360-core.c b/drivers/mfd/mt6360-core.c +index 6eaa6775b8885..d3b32eb798377 100644 +--- a/drivers/mfd/mt6360-core.c ++++ b/drivers/mfd/mt6360-core.c +@@ -402,7 +402,7 @@ static int mt6360_regmap_read(void *context, const void *reg, size_t reg_size, + struct mt6360_ddata *ddata = context; + u8 bank = *(u8 *)reg; + u8 reg_addr = *(u8 *)(reg + 1); +- struct i2c_client *i2c = ddata->i2c[bank]; ++ struct i2c_client *i2c; + bool crc_needed = false; + u8 *buf; + int buf_len = MT6360_ALLOC_READ_SIZE(val_size); +@@ -410,6 +410,11 @@ static int mt6360_regmap_read(void *context, const void *reg, size_t reg_size, + u8 crc; + int ret; + ++ if (bank >= MT6360_SLAVE_MAX) ++ return -EINVAL; ++ ++ i2c = ddata->i2c[bank]; ++ + if (bank == MT6360_SLAVE_PMIC || bank == MT6360_SLAVE_LDO) { + crc_needed = true; + ret = mt6360_xlate_pmicldo_addr(®_addr, val_size); +@@ -453,13 +458,18 @@ static int mt6360_regmap_write(void *context, const void *val, size_t val_size) + struct mt6360_ddata *ddata = context; + u8 bank = *(u8 *)val; + u8 reg_addr = *(u8 *)(val + 1); +- struct i2c_client *i2c = ddata->i2c[bank]; ++ struct i2c_client *i2c; + bool crc_needed = false; + u8 *buf; + int buf_len = MT6360_ALLOC_WRITE_SIZE(val_size); + int write_size = val_size - MT6360_REGMAP_REG_BYTE_SIZE; + int ret; + ++ if (bank >= MT6360_SLAVE_MAX) ++ return -EINVAL; ++ ++ i2c = ddata->i2c[bank]; ++ + if (bank == MT6360_SLAVE_PMIC || bank == MT6360_SLAVE_LDO) { + crc_needed = true; + ret = mt6360_xlate_pmicldo_addr(®_addr, val_size - MT6360_REGMAP_REG_BYTE_SIZE); +diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c +index 4b8ff947762f2..9f3c4a01b4c1c 100644 +--- a/drivers/mfd/qcom-pm8008.c ++++ b/drivers/mfd/qcom-pm8008.c +@@ -215,8 +215,8 @@ static int pm8008_probe(struct i2c_client *client) + + dev = &client->dev; + regmap = devm_regmap_init_i2c(client, &qcom_mfd_regmap_cfg); +- if (!regmap) +- return -ENODEV; ++ if (IS_ERR(regmap)) ++ return PTR_ERR(regmap); + + i2c_set_clientdata(client, regmap); + +diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c +index 71bc34b74bc9c..8fea0e511550a 100644 +--- a/drivers/mfd/qcom_rpm.c ++++ b/drivers/mfd/qcom_rpm.c +@@ -547,7 +547,7 @@ static int qcom_rpm_probe(struct platform_device *pdev) + init_completion(&rpm->ack); + + /* Enable message RAM clock */ +- rpm->ramclk = devm_clk_get(&pdev->dev, "ram"); ++ rpm->ramclk = devm_clk_get_enabled(&pdev->dev, "ram"); + if (IS_ERR(rpm->ramclk)) { + ret = PTR_ERR(rpm->ramclk); + if (ret == -EPROBE_DEFER) +@@ -558,7 +558,6 @@ static int qcom_rpm_probe(struct platform_device *pdev) + */ + rpm->ramclk = NULL; + } +- clk_prepare_enable(rpm->ramclk); /* Accepts NULL */ + + irq_ack = platform_get_irq_byname(pdev, "ack"); + if (irq_ack < 0) +@@ -673,22 +672,11 @@ static int qcom_rpm_probe(struct platform_device *pdev) + if (ret) + dev_warn(&pdev->dev, "failed to mark wakeup irq as wakeup\n"); + +- return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); +-} +- +-static int qcom_rpm_remove(struct platform_device *pdev) +-{ +- struct qcom_rpm *rpm = dev_get_drvdata(&pdev->dev); +- +- of_platform_depopulate(&pdev->dev); +- clk_disable_unprepare(rpm->ramclk); +- +- return 0; ++ return devm_of_platform_populate(&pdev->dev); + } + + static struct platform_driver qcom_rpm_driver = { + .probe = qcom_rpm_probe, +- .remove = qcom_rpm_remove, + .driver = { + .name = "qcom_rpm", + .of_match_table = qcom_rpm_of_match, +diff --git a/drivers/misc/cxl/guest.c b/drivers/misc/cxl/guest.c +index 375f692ae9d68..fb95a2d5cef48 100644 +--- a/drivers/misc/cxl/guest.c ++++ b/drivers/misc/cxl/guest.c +@@ -965,10 +965,10 @@ int cxl_guest_init_afu(struct cxl *adapter, int slice, struct device_node *afu_n + * if it returns an error! + */ + if ((rc = cxl_register_afu(afu))) +- goto err_put1; ++ goto err_put_dev; + + if ((rc = cxl_sysfs_afu_add(afu))) +- goto err_put1; ++ goto err_del_dev; + + /* + * pHyp doesn't expose the programming models supported by the +@@ -984,7 +984,7 @@ int cxl_guest_init_afu(struct cxl *adapter, int slice, struct device_node *afu_n + afu->modes_supported = CXL_MODE_DIRECTED; + + if ((rc = cxl_afu_select_best_mode(afu))) +- goto err_put2; ++ goto err_remove_sysfs; + + adapter->afu[afu->slice] = afu; + +@@ -1004,10 +1004,12 @@ int cxl_guest_init_afu(struct cxl *adapter, int slice, struct device_node *afu_n + + return 0; + +-err_put2: ++err_remove_sysfs: + cxl_sysfs_afu_remove(afu); +-err_put1: +- device_unregister(&afu->dev); ++err_del_dev: ++ device_del(&afu->dev); ++err_put_dev: ++ put_device(&afu->dev); + free = false; + guest_release_serr_irq(afu); + err2: +@@ -1141,18 +1143,20 @@ struct cxl *cxl_guest_init_adapter(struct device_node *np, struct platform_devic + * even if it returns an error! + */ + if ((rc = cxl_register_adapter(adapter))) +- goto err_put1; ++ goto err_put_dev; + + if ((rc = cxl_sysfs_adapter_add(adapter))) +- goto err_put1; ++ goto err_del_dev; + + /* release the context lock as the adapter is configured */ + cxl_adapter_context_unlock(adapter); + + return adapter; + +-err_put1: +- device_unregister(&adapter->dev); ++err_del_dev: ++ device_del(&adapter->dev); ++err_put_dev: ++ put_device(&adapter->dev); + free = false; + cxl_guest_remove_chardev(adapter); + err1: +diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c +index 3de0aea62ade4..0ff944860dda9 100644 +--- a/drivers/misc/cxl/pci.c ++++ b/drivers/misc/cxl/pci.c +@@ -387,6 +387,7 @@ int cxl_calc_capp_routing(struct pci_dev *dev, u64 *chipid, + rc = get_phb_index(np, phb_index); + if (rc) { + pr_err("cxl: invalid phb index\n"); ++ of_node_put(np); + return rc; + } + +@@ -1164,10 +1165,10 @@ static int pci_init_afu(struct cxl *adapter, int slice, struct pci_dev *dev) + * if it returns an error! + */ + if ((rc = cxl_register_afu(afu))) +- goto err_put1; ++ goto err_put_dev; + + if ((rc = cxl_sysfs_afu_add(afu))) +- goto err_put1; ++ goto err_del_dev; + + adapter->afu[afu->slice] = afu; + +@@ -1176,10 +1177,12 @@ static int pci_init_afu(struct cxl *adapter, int slice, struct pci_dev *dev) + + return 0; + +-err_put1: ++err_del_dev: ++ device_del(&afu->dev); ++err_put_dev: + pci_deconfigure_afu(afu); + cxl_debugfs_afu_remove(afu); +- device_unregister(&afu->dev); ++ put_device(&afu->dev); + return rc; + + err_free_native: +@@ -1667,23 +1670,25 @@ static struct cxl *cxl_pci_init_adapter(struct pci_dev *dev) + * even if it returns an error! + */ + if ((rc = cxl_register_adapter(adapter))) +- goto err_put1; ++ goto err_put_dev; + + if ((rc = cxl_sysfs_adapter_add(adapter))) +- goto err_put1; ++ goto err_del_dev; + + /* Release the context lock as adapter is configured */ + cxl_adapter_context_unlock(adapter); + + return adapter; + +-err_put1: ++err_del_dev: ++ device_del(&adapter->dev); ++err_put_dev: + /* This should mirror cxl_remove_adapter, except without the + * sysfs parts + */ + cxl_debugfs_adapter_remove(adapter); + cxl_deconfigure_adapter(adapter); +- device_unregister(&adapter->dev); ++ put_device(&adapter->dev); + return ERR_PTR(rc); + + err_release: +diff --git a/drivers/misc/habanalabs/common/firmware_if.c b/drivers/misc/habanalabs/common/firmware_if.c +index 2de6a9bd564de..f18e53bbba6bb 100644 +--- a/drivers/misc/habanalabs/common/firmware_if.c ++++ b/drivers/misc/habanalabs/common/firmware_if.c +@@ -2983,7 +2983,7 @@ static int hl_fw_get_sec_attest_data(struct hl_device *hdev, u32 packet_id, void + int rc; + + req_cpu_addr = hl_cpu_accessible_dma_pool_alloc(hdev, size, &req_dma_addr); +- if (!data) { ++ if (!req_cpu_addr) { + dev_err(hdev->dev, + "Failed to allocate DMA memory for CPU-CP packet %u\n", packet_id); + return -ENOMEM; +diff --git a/drivers/misc/lkdtm/cfi.c b/drivers/misc/lkdtm/cfi.c +index 5245cf6013c95..fc28714ae3a61 100644 +--- a/drivers/misc/lkdtm/cfi.c ++++ b/drivers/misc/lkdtm/cfi.c +@@ -54,7 +54,11 @@ static void lkdtm_CFI_FORWARD_PROTO(void) + # ifdef CONFIG_ARM64_BTI_KERNEL + # define __no_pac "branch-protection=bti" + # else +-# define __no_pac "branch-protection=none" ++# ifdef CONFIG_CC_HAS_BRANCH_PROT_PAC_RET ++# define __no_pac "branch-protection=none" ++# else ++# define __no_pac "sign-return-address=none" ++# endif + # endif + # define __no_ret_protection __noscs __attribute__((__target__(__no_pac))) + #else +diff --git a/drivers/misc/ocxl/config.c b/drivers/misc/ocxl/config.c +index e401a51596b9c..92ab49705f645 100644 +--- a/drivers/misc/ocxl/config.c ++++ b/drivers/misc/ocxl/config.c +@@ -193,6 +193,18 @@ static int read_dvsec_vendor(struct pci_dev *dev) + return 0; + } + ++/** ++ * get_dvsec_vendor0() - Find a related PCI device (function 0) ++ * @dev: PCI device to match ++ * @dev0: The PCI device (function 0) found ++ * @out_pos: The position of PCI device (function 0) ++ * ++ * Returns 0 on success, negative on failure. ++ * ++ * NOTE: If it's successful, the reference of dev0 is increased, ++ * so after using it, the callers must call pci_dev_put() to give ++ * up the reference. ++ */ + static int get_dvsec_vendor0(struct pci_dev *dev, struct pci_dev **dev0, + int *out_pos) + { +@@ -202,10 +214,14 @@ static int get_dvsec_vendor0(struct pci_dev *dev, struct pci_dev **dev0, + dev = get_function_0(dev); + if (!dev) + return -1; ++ } else { ++ dev = pci_dev_get(dev); + } + pos = find_dvsec(dev, OCXL_DVSEC_VENDOR_ID); +- if (!pos) ++ if (!pos) { ++ pci_dev_put(dev); + return -1; ++ } + *dev0 = dev; + *out_pos = pos; + return 0; +@@ -222,6 +238,7 @@ int ocxl_config_get_reset_reload(struct pci_dev *dev, int *val) + + pci_read_config_dword(dev0, pos + OCXL_DVSEC_VENDOR_RESET_RELOAD, + &reset_reload); ++ pci_dev_put(dev0); + *val = !!(reset_reload & BIT(0)); + return 0; + } +@@ -243,6 +260,7 @@ int ocxl_config_set_reset_reload(struct pci_dev *dev, int val) + reset_reload &= ~BIT(0); + pci_write_config_dword(dev0, pos + OCXL_DVSEC_VENDOR_RESET_RELOAD, + reset_reload); ++ pci_dev_put(dev0); + return 0; + } + +diff --git a/drivers/misc/ocxl/file.c b/drivers/misc/ocxl/file.c +index d46dba2df5a10..452d5777a0e4c 100644 +--- a/drivers/misc/ocxl/file.c ++++ b/drivers/misc/ocxl/file.c +@@ -541,8 +541,11 @@ int ocxl_file_register_afu(struct ocxl_afu *afu) + goto err_put; + + rc = device_register(&info->dev); +- if (rc) +- goto err_put; ++ if (rc) { ++ free_minor(info); ++ put_device(&info->dev); ++ return rc; ++ } + + rc = ocxl_sysfs_register_afu(info); + if (rc) +diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c +index d7ef61e602ede..b836936e97471 100644 +--- a/drivers/misc/sgi-gru/grufault.c ++++ b/drivers/misc/sgi-gru/grufault.c +@@ -648,6 +648,7 @@ int gru_handle_user_call_os(unsigned long cb) + if ((cb & (GRU_HANDLE_STRIDE - 1)) || ucbnum >= GRU_NUM_CB) + return -EINVAL; + ++again: + gts = gru_find_lock_gts(cb); + if (!gts) + return -EINVAL; +@@ -656,7 +657,11 @@ int gru_handle_user_call_os(unsigned long cb) + if (ucbnum >= gts->ts_cbr_au_count * GRU_CBR_AU_SIZE) + goto exit; + +- gru_check_context_placement(gts); ++ if (gru_check_context_placement(gts)) { ++ gru_unlock_gts(gts); ++ gru_unload_context(gts, 1); ++ goto again; ++ } + + /* + * CCH may contain stale data if ts_force_cch_reload is set. +@@ -874,7 +879,11 @@ int gru_set_context_option(unsigned long arg) + } else { + gts->ts_user_blade_id = req.val1; + gts->ts_user_chiplet_id = req.val0; +- gru_check_context_placement(gts); ++ if (gru_check_context_placement(gts)) { ++ gru_unlock_gts(gts); ++ gru_unload_context(gts, 1); ++ return ret; ++ } + } + break; + case sco_gseg_owner: +diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c +index 6706ef3c59776..4eb4b94551390 100644 +--- a/drivers/misc/sgi-gru/grumain.c ++++ b/drivers/misc/sgi-gru/grumain.c +@@ -716,9 +716,10 @@ static int gru_check_chiplet_assignment(struct gru_state *gru, + * chiplet. Misassignment can occur if the process migrates to a different + * blade or if the user changes the selected blade/chiplet. + */ +-void gru_check_context_placement(struct gru_thread_state *gts) ++int gru_check_context_placement(struct gru_thread_state *gts) + { + struct gru_state *gru; ++ int ret = 0; + + /* + * If the current task is the context owner, verify that the +@@ -726,15 +727,23 @@ void gru_check_context_placement(struct gru_thread_state *gts) + * references. Pthread apps use non-owner references to the CBRs. + */ + gru = gts->ts_gru; ++ /* ++ * If gru or gts->ts_tgid_owner isn't initialized properly, return ++ * success to indicate that the caller does not need to unload the ++ * gru context.The caller is responsible for their inspection and ++ * reinitialization if needed. ++ */ + if (!gru || gts->ts_tgid_owner != current->tgid) +- return; ++ return ret; + + if (!gru_check_chiplet_assignment(gru, gts)) { + STAT(check_context_unload); +- gru_unload_context(gts, 1); ++ ret = -EINVAL; + } else if (gru_retarget_intr(gts)) { + STAT(check_context_retarget_intr); + } ++ ++ return ret; + } + + +@@ -934,7 +943,12 @@ again: + mutex_lock(>s->ts_ctxlock); + preempt_disable(); + +- gru_check_context_placement(gts); ++ if (gru_check_context_placement(gts)) { ++ preempt_enable(); ++ mutex_unlock(>s->ts_ctxlock); ++ gru_unload_context(gts, 1); ++ return VM_FAULT_NOPAGE; ++ } + + if (!gts->ts_gru) { + STAT(load_user_context); +diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h +index 8c52776db2341..640daf1994df7 100644 +--- a/drivers/misc/sgi-gru/grutables.h ++++ b/drivers/misc/sgi-gru/grutables.h +@@ -632,7 +632,7 @@ extern int gru_user_flush_tlb(unsigned long arg); + extern int gru_user_unload_context(unsigned long arg); + extern int gru_get_exception_detail(unsigned long arg); + extern int gru_set_context_option(unsigned long address); +-extern void gru_check_context_placement(struct gru_thread_state *gts); ++extern int gru_check_context_placement(struct gru_thread_state *gts); + extern int gru_cpu_fault_map_id(void); + extern struct vm_area_struct *gru_find_vma(unsigned long vaddr); + extern void gru_flush_all_tlb(struct gru_state *gru); +diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c +index 017c2f7d62871..7dd86a9858aba 100644 +--- a/drivers/misc/tifm_7xx1.c ++++ b/drivers/misc/tifm_7xx1.c +@@ -190,7 +190,7 @@ static void tifm_7xx1_switch_media(struct work_struct *work) + spin_unlock_irqrestore(&fm->lock, flags); + } + if (sock) +- tifm_free_device(&sock->dev); ++ put_device(&sock->dev); + } + spin_lock_irqsave(&fm->lock, flags); + } +diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c +index 3662bf5320ce5..72b664ed90cf6 100644 +--- a/drivers/mmc/core/sd.c ++++ b/drivers/mmc/core/sd.c +@@ -1259,7 +1259,7 @@ static int sd_read_ext_regs(struct mmc_card *card) + */ + err = sd_read_ext_reg(card, 0, 0, 0, 512, gen_info_buf); + if (err) { +- pr_warn("%s: error %d reading general info of SD ext reg\n", ++ pr_err("%s: error %d reading general info of SD ext reg\n", + mmc_hostname(card->host), err); + goto out; + } +@@ -1273,7 +1273,12 @@ static int sd_read_ext_regs(struct mmc_card *card) + /* Number of extensions to be find. */ + num_ext = gen_info_buf[4]; + +- /* We support revision 0, but limit it to 512 bytes for simplicity. */ ++ /* ++ * We only support revision 0 and limit it to 512 bytes for simplicity. ++ * No matter what, let's return zero to allow us to continue using the ++ * card, even if we can't support the features from the SD function ++ * extensions registers. ++ */ + if (rev != 0 || len > 512) { + pr_warn("%s: non-supported SD ext reg layout\n", + mmc_hostname(card->host)); +@@ -1288,7 +1293,7 @@ static int sd_read_ext_regs(struct mmc_card *card) + for (i = 0; i < num_ext; i++) { + err = sd_parse_ext_reg(card, gen_info_buf, &next_ext_addr); + if (err) { +- pr_warn("%s: error %d parsing SD ext reg\n", ++ pr_err("%s: error %d parsing SD ext reg\n", + mmc_hostname(card->host), err); + goto out; + } +diff --git a/drivers/mmc/host/alcor.c b/drivers/mmc/host/alcor.c +index bfb8efeb7eb80..d01df01d4b4d1 100644 +--- a/drivers/mmc/host/alcor.c ++++ b/drivers/mmc/host/alcor.c +@@ -1114,7 +1114,10 @@ static int alcor_pci_sdmmc_drv_probe(struct platform_device *pdev) + alcor_hw_init(host); + + dev_set_drvdata(&pdev->dev, host); +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto free_host; ++ + return 0; + + free_host: +diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c +index 91d52ba7a39fc..bb9bbf1c927b6 100644 +--- a/drivers/mmc/host/atmel-mci.c ++++ b/drivers/mmc/host/atmel-mci.c +@@ -2222,6 +2222,7 @@ static int atmci_init_slot(struct atmel_mci *host, + { + struct mmc_host *mmc; + struct atmel_mci_slot *slot; ++ int ret; + + mmc = mmc_alloc_host(sizeof(struct atmel_mci_slot), &host->pdev->dev); + if (!mmc) +@@ -2305,11 +2306,13 @@ static int atmci_init_slot(struct atmel_mci *host, + + host->slot[id] = slot; + mmc_regulator_get_supply(mmc); +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) { ++ mmc_free_host(mmc); ++ return ret; ++ } + + if (gpio_is_valid(slot->detect_pin)) { +- int ret; +- + timer_setup(&slot->detect_timer, atmci_detect_change, 0); + + ret = request_irq(gpio_to_irq(slot->detect_pin), +diff --git a/drivers/mmc/host/litex_mmc.c b/drivers/mmc/host/litex_mmc.c +index 6ba0d63b8c078..39c6707fdfdbc 100644 +--- a/drivers/mmc/host/litex_mmc.c ++++ b/drivers/mmc/host/litex_mmc.c +@@ -502,6 +502,7 @@ static int litex_mmc_irq_init(struct platform_device *pdev, + + use_polling: + host->mmc->caps |= MMC_CAP_NEEDS_POLL; ++ host->irq = 0; + return 0; + } + +diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c +index df05e60bed9a2..6e5ea0213b477 100644 +--- a/drivers/mmc/host/meson-gx-mmc.c ++++ b/drivers/mmc/host/meson-gx-mmc.c +@@ -1335,7 +1335,9 @@ static int meson_mmc_probe(struct platform_device *pdev) + } + + mmc->ops = &meson_mmc_ops; +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto err_free_irq; + + return 0; + +diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c +index 012aa85489d86..b9e5dfe74e5c7 100644 +--- a/drivers/mmc/host/mmci.c ++++ b/drivers/mmc/host/mmci.c +@@ -2256,7 +2256,9 @@ static int mmci_probe(struct amba_device *dev, + pm_runtime_set_autosuspend_delay(&dev->dev, 50); + pm_runtime_use_autosuspend(&dev->dev); + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto clk_disable; + + pm_runtime_put(&dev->dev); + return 0; +diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c +index dfc3ffd5b1f8c..52ed30f2d9f4f 100644 +--- a/drivers/mmc/host/moxart-mmc.c ++++ b/drivers/mmc/host/moxart-mmc.c +@@ -665,7 +665,9 @@ static int moxart_probe(struct platform_device *pdev) + goto out; + + dev_set_drvdata(dev, mmc); +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto out; + + dev_dbg(dev, "IRQ=%d, FIFO is %d bytes\n", irq, host->fifo_width); + +diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c +index 2cf0413407ea2..668f865f3efb0 100644 +--- a/drivers/mmc/host/mxcmmc.c ++++ b/drivers/mmc/host/mxcmmc.c +@@ -1143,7 +1143,9 @@ static int mxcmci_probe(struct platform_device *pdev) + + timer_setup(&host->watchdog, mxcmci_watchdog, 0); + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto out_free_dma; + + return 0; + +diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c +index fca30add563e9..4bd7447552055 100644 +--- a/drivers/mmc/host/omap_hsmmc.c ++++ b/drivers/mmc/host/omap_hsmmc.c +@@ -1946,7 +1946,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev) + if (!ret) + mmc->caps |= MMC_CAP_SDIO_IRQ; + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto err_irq; + + if (mmc_pdata(host)->name != NULL) { + ret = device_create_file(&mmc->class_dev, &dev_attr_slot_name); +diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c +index e4003f6058eb5..2a988f942b6ca 100644 +--- a/drivers/mmc/host/pxamci.c ++++ b/drivers/mmc/host/pxamci.c +@@ -763,7 +763,12 @@ static int pxamci_probe(struct platform_device *pdev) + dev_warn(dev, "gpio_ro and get_ro() both defined\n"); + } + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) { ++ if (host->pdata && host->pdata->exit) ++ host->pdata->exit(dev, mmc); ++ goto out; ++ } + + return 0; + +diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h +index c4abfee1ebae1..e4c490729c98e 100644 +--- a/drivers/mmc/host/renesas_sdhi.h ++++ b/drivers/mmc/host/renesas_sdhi.h +@@ -44,6 +44,7 @@ struct renesas_sdhi_quirks { + bool fixed_addr_mode; + bool dma_one_rx_only; + bool manual_tap_correction; ++ bool old_info1_layout; + u32 hs400_bad_taps; + const u8 (*hs400_calib_table)[SDHI_CALIB_TABLE_MAX]; + }; +diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c +index b970699743e0a..e38d0e8b8e0ed 100644 +--- a/drivers/mmc/host/renesas_sdhi_core.c ++++ b/drivers/mmc/host/renesas_sdhi_core.c +@@ -546,7 +546,7 @@ static void renesas_sdhi_reset_hs400_mode(struct tmio_mmc_host *host, + SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL) & + sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2)); + +- if (priv->adjust_hs400_calib_table) ++ if (priv->quirks && (priv->quirks->hs400_calib_table || priv->quirks->hs400_bad_taps)) + renesas_sdhi_adjust_hs400_mode_disable(host); + + sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN | +@@ -1068,11 +1068,14 @@ int renesas_sdhi_probe(struct platform_device *pdev, + if (ver >= SDHI_VER_GEN3_SD) + host->get_timeout_cycles = renesas_sdhi_gen3_get_cycles; + ++ /* Check for SCC so we can reset it if needed */ ++ if (of_data && of_data->scc_offset && ver >= SDHI_VER_GEN2_SDR104) ++ priv->scc_ctl = host->ctl + of_data->scc_offset; ++ + /* Enable tuning iff we have an SCC and a supported mode */ +- if (of_data && of_data->scc_offset && +- (host->mmc->caps & MMC_CAP_UHS_SDR104 || +- host->mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR | +- MMC_CAP2_HS400_1_8V))) { ++ if (priv->scc_ctl && (host->mmc->caps & MMC_CAP_UHS_SDR104 || ++ host->mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR | ++ MMC_CAP2_HS400_1_8V))) { + const struct renesas_sdhi_scc *taps = of_data->taps; + bool use_4tap = quirks && quirks->hs400_4taps; + bool hit = false; +@@ -1092,7 +1095,6 @@ int renesas_sdhi_probe(struct platform_device *pdev, + if (!hit) + dev_warn(&host->pdev->dev, "Unknown clock rate for tuning\n"); + +- priv->scc_ctl = host->ctl + of_data->scc_offset; + host->check_retune = renesas_sdhi_check_scc_error; + host->ops.execute_tuning = renesas_sdhi_execute_tuning; + host->ops.prepare_hs400_tuning = renesas_sdhi_prepare_hs400_tuning; +diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c +index 42937596c4c41..7c81c2680701f 100644 +--- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c ++++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c +@@ -49,7 +49,8 @@ + /* DM_CM_INFO1 and DM_CM_INFO1_MASK */ + #define INFO1_CLEAR 0 + #define INFO1_MASK_CLEAR GENMASK_ULL(31, 0) +-#define INFO1_DTRANEND1 BIT(17) ++#define INFO1_DTRANEND1 BIT(20) ++#define INFO1_DTRANEND1_OLD BIT(17) + #define INFO1_DTRANEND0 BIT(16) + + /* DM_CM_INFO2 and DM_CM_INFO2_MASK */ +@@ -165,6 +166,7 @@ static const struct renesas_sdhi_quirks sdhi_quirks_4tap_nohs400_one_rx = { + .hs400_disabled = true, + .hs400_4taps = true, + .dma_one_rx_only = true, ++ .old_info1_layout = true, + }; + + static const struct renesas_sdhi_quirks sdhi_quirks_4tap = { +diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c +index e1580f78c6b2d..8098726dcc0bf 100644 +--- a/drivers/mmc/host/rtsx_pci_sdmmc.c ++++ b/drivers/mmc/host/rtsx_pci_sdmmc.c +@@ -1474,6 +1474,7 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev) + struct realtek_pci_sdmmc *host; + struct rtsx_pcr *pcr; + struct pcr_handle *handle = pdev->dev.platform_data; ++ int ret; + + if (!handle) + return -ENXIO; +@@ -1511,7 +1512,13 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev) + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_use_autosuspend(&pdev->dev); + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) { ++ pm_runtime_dont_use_autosuspend(&pdev->dev); ++ pm_runtime_disable(&pdev->dev); ++ mmc_free_host(mmc); ++ return ret; ++ } + + return 0; + } +diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c +index 5798aee066531..2c650cd58693e 100644 +--- a/drivers/mmc/host/rtsx_usb_sdmmc.c ++++ b/drivers/mmc/host/rtsx_usb_sdmmc.c +@@ -1329,6 +1329,7 @@ static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev) + #ifdef RTSX_USB_USE_LEDS_CLASS + int err; + #endif ++ int ret; + + ucr = usb_get_intfdata(to_usb_interface(pdev->dev.parent)); + if (!ucr) +@@ -1365,7 +1366,15 @@ static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev) + INIT_WORK(&host->led_work, rtsx_usb_update_led); + + #endif +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) { ++#ifdef RTSX_USB_USE_LEDS_CLASS ++ led_classdev_unregister(&host->led); ++#endif ++ mmc_free_host(mmc); ++ pm_runtime_disable(&pdev->dev); ++ return ret; ++ } + + return 0; + } +diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c +index c71000a07656e..1adaa94c31aca 100644 +--- a/drivers/mmc/host/sdhci-tegra.c ++++ b/drivers/mmc/host/sdhci-tegra.c +@@ -1526,7 +1526,8 @@ static const struct sdhci_pltfm_data sdhci_tegra186_pdata = { + SDHCI_QUIRK_NO_HISPD_BIT | + SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | + SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, +- .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, ++ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | ++ SDHCI_QUIRK2_ISSUE_CMD_DAT_RESET_TOGETHER, + .ops = &tegra186_sdhci_ops, + }; + +diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c +index c7ad32a75b570..632341911b6e7 100644 +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c +@@ -270,6 +270,11 @@ enum sdhci_reset_reason { + + static void sdhci_reset_for_reason(struct sdhci_host *host, enum sdhci_reset_reason reason) + { ++ if (host->quirks2 & SDHCI_QUIRK2_ISSUE_CMD_DAT_RESET_TOGETHER) { ++ sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); ++ return; ++ } ++ + switch (reason) { + case SDHCI_RESET_FOR_INIT: + sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); +diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h +index 87a3aaa074387..5ce7cdcc192fd 100644 +--- a/drivers/mmc/host/sdhci.h ++++ b/drivers/mmc/host/sdhci.h +@@ -478,6 +478,8 @@ struct sdhci_host { + * block count. + */ + #define SDHCI_QUIRK2_USE_32BIT_BLK_CNT (1<<18) ++/* Issue CMD and DATA reset together */ ++#define SDHCI_QUIRK2_ISSUE_CMD_DAT_RESET_TOGETHER (1<<19) + + int irq; /* Device IRQ */ + void __iomem *ioaddr; /* Mapped address */ +diff --git a/drivers/mmc/host/sdhci_f_sdh30.c b/drivers/mmc/host/sdhci_f_sdh30.c +index 3f5977979cf25..6c4f43e112826 100644 +--- a/drivers/mmc/host/sdhci_f_sdh30.c ++++ b/drivers/mmc/host/sdhci_f_sdh30.c +@@ -168,6 +168,9 @@ static int sdhci_f_sdh30_probe(struct platform_device *pdev) + if (reg & SDHCI_CAN_DO_8BIT) + priv->vendor_hs200 = F_SDH30_EMMC_HS200; + ++ if (!(reg & SDHCI_TIMEOUT_CLK_MASK)) ++ host->quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK; ++ + ret = sdhci_add_host(host); + if (ret) + goto err_add_host; +diff --git a/drivers/mmc/host/toshsd.c b/drivers/mmc/host/toshsd.c +index 8d037c2071abc..497791ffada6d 100644 +--- a/drivers/mmc/host/toshsd.c ++++ b/drivers/mmc/host/toshsd.c +@@ -651,7 +651,9 @@ static int toshsd_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + if (ret) + goto unmap; + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto free_irq; + + base = pci_resource_start(pdev, 0); + dev_dbg(&pdev->dev, "MMIO %pa, IRQ %d\n", &base, pdev->irq); +@@ -660,6 +662,8 @@ static int toshsd_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + + return 0; + ++free_irq: ++ free_irq(pdev->irq, host); + unmap: + pci_iounmap(pdev, host->ioaddr); + release: +diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c +index 88662a90ed960..a2b0d9461665b 100644 +--- a/drivers/mmc/host/via-sdmmc.c ++++ b/drivers/mmc/host/via-sdmmc.c +@@ -1151,7 +1151,9 @@ static int via_sd_probe(struct pci_dev *pcidev, + pcidev->subsystem_device == 0x3891) + sdhost->quirks = VIA_CRDR_QUIRK_300MS_PWRDELAY; + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto unmap; + + return 0; + +diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c +index 97beece62fec4..72f65f32abbc7 100644 +--- a/drivers/mmc/host/vub300.c ++++ b/drivers/mmc/host/vub300.c +@@ -2049,6 +2049,7 @@ static void vub300_enable_sdio_irq(struct mmc_host *mmc, int enable) + return; + kref_get(&vub300->kref); + if (enable) { ++ set_current_state(TASK_RUNNING); + mutex_lock(&vub300->irq_mutex); + if (vub300->irqs_queued) { + vub300->irqs_queued -= 1; +@@ -2064,6 +2065,7 @@ static void vub300_enable_sdio_irq(struct mmc_host *mmc, int enable) + vub300_queue_poll_work(vub300, 0); + } + mutex_unlock(&vub300->irq_mutex); ++ set_current_state(TASK_INTERRUPTIBLE); + } else { + vub300->irq_enabled = 0; + } +@@ -2299,14 +2301,14 @@ static int vub300_probe(struct usb_interface *interface, + 0x0000, 0x0000, &vub300->system_port_status, + sizeof(vub300->system_port_status), 1000); + if (retval < 0) { +- goto error4; ++ goto error5; + } else if (sizeof(vub300->system_port_status) == retval) { + vub300->card_present = + (0x0001 & vub300->system_port_status.port_flags) ? 1 : 0; + vub300->read_only = + (0x0010 & vub300->system_port_status.port_flags) ? 1 : 0; + } else { +- goto error4; ++ goto error5; + } + usb_set_intfdata(interface, vub300); + INIT_DELAYED_WORK(&vub300->pollwork, vub300_pollwork_thread); +@@ -2329,8 +2331,13 @@ static int vub300_probe(struct usb_interface *interface, + "USB vub300 remote SDIO host controller[%d]" + "connected with no SD/SDIO card inserted\n", + interface_to_InterfaceNumber(interface)); +- mmc_add_host(mmc); ++ retval = mmc_add_host(mmc); ++ if (retval) ++ goto error6; ++ + return 0; ++error6: ++ del_timer_sync(&vub300->inactivity_timer); + error5: + mmc_free_host(mmc); + /* +diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c +index 67ecd342fe5f1..7c7ec8d10232b 100644 +--- a/drivers/mmc/host/wbsd.c ++++ b/drivers/mmc/host/wbsd.c +@@ -1698,7 +1698,17 @@ static int wbsd_init(struct device *dev, int base, int irq, int dma, + */ + wbsd_init_device(host); + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) { ++ if (!pnp) ++ wbsd_chip_poweroff(host); ++ ++ wbsd_release_resources(host); ++ wbsd_free_mmc(dev); ++ ++ mmc_free_host(mmc); ++ return ret; ++ } + + pr_info("%s: W83L51xD", mmc_hostname(mmc)); + if (host->chip_id != 0) +diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c +index 9b5c503e3a3fc..9aa3027ca25e4 100644 +--- a/drivers/mmc/host/wmt-sdmmc.c ++++ b/drivers/mmc/host/wmt-sdmmc.c +@@ -856,11 +856,15 @@ static int wmt_mci_probe(struct platform_device *pdev) + /* configure the controller to a known 'ready' state */ + wmt_reset_hardware(mmc); + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto fail7; + + dev_info(&pdev->dev, "WMT SDHC Controller initialized\n"); + + return 0; ++fail7: ++ clk_disable_unprepare(priv->clk_sdmmc); + fail6: + clk_put(priv->clk_sdmmc); + fail5_and_a_half: +diff --git a/drivers/mtd/lpddr/lpddr2_nvm.c b/drivers/mtd/lpddr/lpddr2_nvm.c +index 367e2d906de02..e71af4c490969 100644 +--- a/drivers/mtd/lpddr/lpddr2_nvm.c ++++ b/drivers/mtd/lpddr/lpddr2_nvm.c +@@ -433,6 +433,8 @@ static int lpddr2_nvm_probe(struct platform_device *pdev) + + /* lpddr2_nvm address range */ + add_range = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!add_range) ++ return -ENODEV; + + /* Populate map_info data structure */ + *map = (struct map_info) { +diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c +index 1749dbbacc135..62a5bf41a6d72 100644 +--- a/drivers/mtd/maps/pxa2xx-flash.c ++++ b/drivers/mtd/maps/pxa2xx-flash.c +@@ -64,6 +64,7 @@ static int pxa2xx_flash_probe(struct platform_device *pdev) + if (!info->map.virt) { + printk(KERN_WARNING "Failed to ioremap %s\n", + info->map.name); ++ kfree(info); + return -ENOMEM; + } + info->map.cached = ioremap_cache(info->map.phys, info->map.size); +@@ -85,6 +86,7 @@ static int pxa2xx_flash_probe(struct platform_device *pdev) + iounmap((void *)info->map.virt); + if (info->map.cached) + iounmap(info->map.cached); ++ kfree(info); + return -EIO; + } + info->mtd->dev.parent = &pdev->dev; +diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c +index 0b4ca0aa41321..686ada1a63e9a 100644 +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -723,8 +723,10 @@ int add_mtd_device(struct mtd_info *mtd) + mtd_check_of_node(mtd); + of_node_get(mtd_get_of_node(mtd)); + error = device_register(&mtd->dev); +- if (error) ++ if (error) { ++ put_device(&mtd->dev); + goto fail_added; ++ } + + /* Add the nvmem provider */ + error = mtd_nvmem_add(mtd); +@@ -774,6 +776,7 @@ int del_mtd_device(struct mtd_info *mtd) + { + int ret; + struct mtd_notifier *not; ++ struct device_node *mtd_of_node; + + mutex_lock(&mtd_table_mutex); + +@@ -792,6 +795,7 @@ int del_mtd_device(struct mtd_info *mtd) + mtd->index, mtd->name, mtd->usecount); + ret = -EBUSY; + } else { ++ mtd_of_node = mtd_get_of_node(mtd); + debugfs_remove_recursive(mtd->dbg.dfs_dir); + + /* Try to remove the NVMEM provider */ +@@ -803,7 +807,7 @@ int del_mtd_device(struct mtd_info *mtd) + memset(&mtd->dev, 0, sizeof(mtd->dev)); + + idr_remove(&mtd_idr, mtd->index); +- of_node_put(mtd_get_of_node(mtd)); ++ of_node_put(mtd_of_node); + + module_put(THIS_MODULE); + ret = 0; +@@ -2483,6 +2487,7 @@ static int __init init_mtd(void) + out_procfs: + if (proc_mtd) + remove_proc_entry("mtd", NULL); ++ bdi_unregister(mtd_bdi); + bdi_put(mtd_bdi); + err_bdi: + class_unregister(&mtd_class); +diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c +index bee8fc4c9f078..0cf1a1797ea32 100644 +--- a/drivers/mtd/spi-nor/core.c ++++ b/drivers/mtd/spi-nor/core.c +@@ -1914,7 +1914,8 @@ static int spi_nor_spimem_check_readop(struct spi_nor *nor, + spi_nor_spimem_setup_op(nor, &op, read->proto); + + /* convert the dummy cycles to the number of bytes */ +- op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8; ++ op.dummy.nbytes = (read->num_mode_clocks + read->num_wait_states) * ++ op.dummy.buswidth / 8; + if (spi_nor_protocol_is_dtr(nor->read_proto)) + op.dummy.nbytes *= 2; + +diff --git a/drivers/mtd/spi-nor/sysfs.c b/drivers/mtd/spi-nor/sysfs.c +index 9aec9d8a98ada..4c3b351aef245 100644 +--- a/drivers/mtd/spi-nor/sysfs.c ++++ b/drivers/mtd/spi-nor/sysfs.c +@@ -67,6 +67,19 @@ static struct bin_attribute *spi_nor_sysfs_bin_entries[] = { + NULL + }; + ++static umode_t spi_nor_sysfs_is_visible(struct kobject *kobj, ++ struct attribute *attr, int n) ++{ ++ struct spi_device *spi = to_spi_device(kobj_to_dev(kobj)); ++ struct spi_mem *spimem = spi_get_drvdata(spi); ++ struct spi_nor *nor = spi_mem_get_drvdata(spimem); ++ ++ if (attr == &dev_attr_jedec_id.attr && !nor->info->id_len) ++ return 0; ++ ++ return 0444; ++} ++ + static umode_t spi_nor_sysfs_is_bin_visible(struct kobject *kobj, + struct bin_attribute *attr, int n) + { +@@ -82,6 +95,7 @@ static umode_t spi_nor_sysfs_is_bin_visible(struct kobject *kobj, + + static const struct attribute_group spi_nor_sysfs_group = { + .name = "spi-nor", ++ .is_visible = spi_nor_sysfs_is_visible, + .is_bin_visible = spi_nor_sysfs_is_bin_visible, + .attrs = spi_nor_sysfs_entries, + .bin_attrs = spi_nor_sysfs_bin_entries, +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index b9a882f182d29..b108f2f4adc20 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -2531,12 +2531,21 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in + /* called with rcu_read_lock() */ + static int bond_miimon_inspect(struct bonding *bond) + { ++ bool ignore_updelay = false; + int link_state, commit = 0; + struct list_head *iter; + struct slave *slave; +- bool ignore_updelay; + +- ignore_updelay = !rcu_dereference(bond->curr_active_slave); ++ if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP) { ++ ignore_updelay = !rcu_dereference(bond->curr_active_slave); ++ } else { ++ struct bond_up_slave *usable_slaves; ++ ++ usable_slaves = rcu_dereference(bond->usable_slaves); ++ ++ if (usable_slaves && usable_slaves->count == 0) ++ ignore_updelay = true; ++ } + + bond_for_each_slave_rcu(bond, slave, iter) { + bond_propose_link_state(slave, BOND_LINK_NOCHANGE); +@@ -2644,8 +2653,9 @@ static void bond_miimon_link_change(struct bonding *bond, + + static void bond_miimon_commit(struct bonding *bond) + { +- struct list_head *iter; + struct slave *slave, *primary; ++ bool do_failover = false; ++ struct list_head *iter; + + bond_for_each_slave(bond, slave, iter) { + switch (slave->link_new_state) { +@@ -2689,8 +2699,9 @@ static void bond_miimon_commit(struct bonding *bond) + + bond_miimon_link_change(bond, slave, BOND_LINK_UP); + +- if (!bond->curr_active_slave || slave == primary) +- goto do_failover; ++ if (!rcu_access_pointer(bond->curr_active_slave) || slave == primary || ++ slave->prio > rcu_dereference(bond->curr_active_slave)->prio) ++ do_failover = true; + + continue; + +@@ -2711,7 +2722,7 @@ static void bond_miimon_commit(struct bonding *bond) + bond_miimon_link_change(bond, slave, BOND_LINK_DOWN); + + if (slave == rcu_access_pointer(bond->curr_active_slave)) +- goto do_failover; ++ do_failover = true; + + continue; + +@@ -2722,8 +2733,9 @@ static void bond_miimon_commit(struct bonding *bond) + + continue; + } ++ } + +-do_failover: ++ if (do_failover) { + block_netpoll_tx(); + bond_select_active_slave(bond); + unblock_netpoll_tx(); +@@ -3521,6 +3533,7 @@ static int bond_ab_arp_inspect(struct bonding *bond) + */ + static void bond_ab_arp_commit(struct bonding *bond) + { ++ bool do_failover = false; + struct list_head *iter; + unsigned long last_tx; + struct slave *slave; +@@ -3550,8 +3563,9 @@ static void bond_ab_arp_commit(struct bonding *bond) + slave_info(bond->dev, slave->dev, "link status definitely up\n"); + + if (!rtnl_dereference(bond->curr_active_slave) || +- slave == rtnl_dereference(bond->primary_slave)) +- goto do_failover; ++ slave == rtnl_dereference(bond->primary_slave) || ++ slave->prio > rtnl_dereference(bond->curr_active_slave)->prio) ++ do_failover = true; + + } + +@@ -3570,7 +3584,7 @@ static void bond_ab_arp_commit(struct bonding *bond) + + if (slave == rtnl_dereference(bond->curr_active_slave)) { + RCU_INIT_POINTER(bond->current_arp_slave, NULL); +- goto do_failover; ++ do_failover = true; + } + + continue; +@@ -3594,8 +3608,9 @@ static void bond_ab_arp_commit(struct bonding *bond) + slave->link_new_state); + continue; + } ++ } + +-do_failover: ++ if (do_failover) { + block_netpoll_tx(); + bond_select_active_slave(bond); + unblock_netpoll_tx(); +diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c +index e5575d2755e4b..2de998b98cb5e 100644 +--- a/drivers/net/can/m_can/m_can.c ++++ b/drivers/net/can/m_can/m_can.c +@@ -1233,10 +1233,17 @@ static int m_can_set_bittiming(struct net_device *dev) + * - setup bittiming + * - configure timestamp generation + */ +-static void m_can_chip_config(struct net_device *dev) ++static int m_can_chip_config(struct net_device *dev) + { + struct m_can_classdev *cdev = netdev_priv(dev); + u32 cccr, test; ++ int err; ++ ++ err = m_can_init_ram(cdev); ++ if (err) { ++ dev_err(cdev->dev, "Message RAM configuration failed\n"); ++ return err; ++ } + + m_can_config_endisable(cdev, true); + +@@ -1360,18 +1367,25 @@ static void m_can_chip_config(struct net_device *dev) + + if (cdev->ops->init) + cdev->ops->init(cdev); ++ ++ return 0; + } + +-static void m_can_start(struct net_device *dev) ++static int m_can_start(struct net_device *dev) + { + struct m_can_classdev *cdev = netdev_priv(dev); ++ int ret; + + /* basic m_can configuration */ +- m_can_chip_config(dev); ++ ret = m_can_chip_config(dev); ++ if (ret) ++ return ret; + + cdev->can.state = CAN_STATE_ERROR_ACTIVE; + + m_can_enable_all_interrupts(cdev); ++ ++ return 0; + } + + static int m_can_set_mode(struct net_device *dev, enum can_mode mode) +@@ -1799,7 +1813,9 @@ static int m_can_open(struct net_device *dev) + } + + /* start the m_can controller */ +- m_can_start(dev); ++ err = m_can_start(dev); ++ if (err) ++ goto exit_irq_fail; + + if (!cdev->is_peripheral) + napi_enable(&cdev->napi); +@@ -2058,9 +2074,13 @@ int m_can_class_resume(struct device *dev) + ret = m_can_clk_start(cdev); + if (ret) + return ret; ++ ret = m_can_start(ndev); ++ if (ret) { ++ m_can_clk_stop(cdev); ++ ++ return ret; ++ } + +- m_can_init_ram(cdev); +- m_can_start(ndev); + netif_device_attach(ndev); + netif_start_queue(ndev); + } +diff --git a/drivers/net/can/m_can/m_can_platform.c b/drivers/net/can/m_can/m_can_platform.c +index eee47bad05920..de6d8e01bf2e8 100644 +--- a/drivers/net/can/m_can/m_can_platform.c ++++ b/drivers/net/can/m_can/m_can_platform.c +@@ -140,10 +140,6 @@ static int m_can_plat_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, mcan_class); + +- ret = m_can_init_ram(mcan_class); +- if (ret) +- goto probe_fail; +- + pm_runtime_enable(mcan_class->dev); + ret = m_can_class_register(mcan_class); + if (ret) +diff --git a/drivers/net/can/m_can/tcan4x5x-core.c b/drivers/net/can/m_can/tcan4x5x-core.c +index 41645a24384ce..2342aa011647c 100644 +--- a/drivers/net/can/m_can/tcan4x5x-core.c ++++ b/drivers/net/can/m_can/tcan4x5x-core.c +@@ -10,7 +10,7 @@ + #define TCAN4X5X_DEV_ID1 0x04 + #define TCAN4X5X_REV 0x08 + #define TCAN4X5X_STATUS 0x0C +-#define TCAN4X5X_ERROR_STATUS 0x10 ++#define TCAN4X5X_ERROR_STATUS_MASK 0x10 + #define TCAN4X5X_CONTROL 0x14 + + #define TCAN4X5X_CONFIG 0x800 +@@ -204,17 +204,7 @@ static int tcan4x5x_clear_interrupts(struct m_can_classdev *cdev) + if (ret) + return ret; + +- ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_MCAN_INT_REG, +- TCAN4X5X_ENABLE_MCAN_INT); +- if (ret) +- return ret; +- +- ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_INT_FLAGS, +- TCAN4X5X_CLEAR_ALL_INT); +- if (ret) +- return ret; +- +- return tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_ERROR_STATUS, ++ return tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_INT_FLAGS, + TCAN4X5X_CLEAR_ALL_INT); + } + +@@ -234,8 +224,8 @@ static int tcan4x5x_init(struct m_can_classdev *cdev) + if (ret) + return ret; + +- /* Zero out the MCAN buffers */ +- ret = m_can_init_ram(cdev); ++ ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_ERROR_STATUS_MASK, ++ TCAN4X5X_CLEAR_ALL_INT); + if (ret) + return ret; + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h +index f6c0938027ece..ff10b3790d844 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h +@@ -76,6 +76,14 @@ struct kvaser_usb_tx_urb_context { + u32 echo_index; + }; + ++struct kvaser_usb_busparams { ++ __le32 bitrate; ++ u8 tseg1; ++ u8 tseg2; ++ u8 sjw; ++ u8 nsamples; ++} __packed; ++ + struct kvaser_usb { + struct usb_device *udev; + struct usb_interface *intf; +@@ -104,13 +112,19 @@ struct kvaser_usb_net_priv { + struct can_priv can; + struct can_berr_counter bec; + ++ /* subdriver-specific data */ ++ void *sub_priv; ++ + struct kvaser_usb *dev; + struct net_device *netdev; + int channel; + +- struct completion start_comp, stop_comp, flush_comp; ++ struct completion start_comp, stop_comp, flush_comp, ++ get_busparams_comp; + struct usb_anchor tx_submitted; + ++ struct kvaser_usb_busparams busparams_nominal, busparams_data; ++ + spinlock_t tx_contexts_lock; /* lock for active_tx_contexts */ + int active_tx_contexts; + struct kvaser_usb_tx_urb_context tx_contexts[]; +@@ -120,11 +134,15 @@ struct kvaser_usb_net_priv { + * struct kvaser_usb_dev_ops - Device specific functions + * @dev_set_mode: used for can.do_set_mode + * @dev_set_bittiming: used for can.do_set_bittiming ++ * @dev_get_busparams: readback arbitration busparams + * @dev_set_data_bittiming: used for can.do_set_data_bittiming ++ * @dev_get_data_busparams: readback data busparams + * @dev_get_berr_counter: used for can.do_get_berr_counter + * + * @dev_setup_endpoints: setup USB in and out endpoints + * @dev_init_card: initialize card ++ * @dev_init_channel: initialize channel ++ * @dev_remove_channel: uninitialize channel + * @dev_get_software_info: get software info + * @dev_get_software_details: get software details + * @dev_get_card_info: get card info +@@ -140,12 +158,18 @@ struct kvaser_usb_net_priv { + */ + struct kvaser_usb_dev_ops { + int (*dev_set_mode)(struct net_device *netdev, enum can_mode mode); +- int (*dev_set_bittiming)(struct net_device *netdev); +- int (*dev_set_data_bittiming)(struct net_device *netdev); ++ int (*dev_set_bittiming)(const struct net_device *netdev, ++ const struct kvaser_usb_busparams *busparams); ++ int (*dev_get_busparams)(struct kvaser_usb_net_priv *priv); ++ int (*dev_set_data_bittiming)(const struct net_device *netdev, ++ const struct kvaser_usb_busparams *busparams); ++ int (*dev_get_data_busparams)(struct kvaser_usb_net_priv *priv); + int (*dev_get_berr_counter)(const struct net_device *netdev, + struct can_berr_counter *bec); + int (*dev_setup_endpoints)(struct kvaser_usb *dev); + int (*dev_init_card)(struct kvaser_usb *dev); ++ int (*dev_init_channel)(struct kvaser_usb_net_priv *priv); ++ void (*dev_remove_channel)(struct kvaser_usb_net_priv *priv); + int (*dev_get_software_info)(struct kvaser_usb *dev); + int (*dev_get_software_details)(struct kvaser_usb *dev); + int (*dev_get_card_info)(struct kvaser_usb *dev); +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +index 802e27c0ecedb..3a2bfaad14065 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +@@ -440,10 +440,6 @@ static int kvaser_usb_open(struct net_device *netdev) + if (err) + return err; + +- err = kvaser_usb_setup_rx_urbs(dev); +- if (err) +- goto error; +- + err = ops->dev_set_opt_mode(priv); + if (err) + goto error; +@@ -534,6 +530,93 @@ static int kvaser_usb_close(struct net_device *netdev) + return 0; + } + ++static int kvaser_usb_set_bittiming(struct net_device *netdev) ++{ ++ struct kvaser_usb_net_priv *priv = netdev_priv(netdev); ++ struct kvaser_usb *dev = priv->dev; ++ const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops; ++ struct can_bittiming *bt = &priv->can.bittiming; ++ ++ struct kvaser_usb_busparams busparams; ++ int tseg1 = bt->prop_seg + bt->phase_seg1; ++ int tseg2 = bt->phase_seg2; ++ int sjw = bt->sjw; ++ int err = -EOPNOTSUPP; ++ ++ busparams.bitrate = cpu_to_le32(bt->bitrate); ++ busparams.sjw = (u8)sjw; ++ busparams.tseg1 = (u8)tseg1; ++ busparams.tseg2 = (u8)tseg2; ++ if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ++ busparams.nsamples = 3; ++ else ++ busparams.nsamples = 1; ++ ++ err = ops->dev_set_bittiming(netdev, &busparams); ++ if (err) ++ return err; ++ ++ err = kvaser_usb_setup_rx_urbs(priv->dev); ++ if (err) ++ return err; ++ ++ err = ops->dev_get_busparams(priv); ++ if (err) { ++ /* Treat EOPNOTSUPP as success */ ++ if (err == -EOPNOTSUPP) ++ err = 0; ++ return err; ++ } ++ ++ if (memcmp(&busparams, &priv->busparams_nominal, ++ sizeof(priv->busparams_nominal)) != 0) ++ err = -EINVAL; ++ ++ return err; ++} ++ ++static int kvaser_usb_set_data_bittiming(struct net_device *netdev) ++{ ++ struct kvaser_usb_net_priv *priv = netdev_priv(netdev); ++ struct kvaser_usb *dev = priv->dev; ++ const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops; ++ struct can_bittiming *dbt = &priv->can.data_bittiming; ++ ++ struct kvaser_usb_busparams busparams; ++ int tseg1 = dbt->prop_seg + dbt->phase_seg1; ++ int tseg2 = dbt->phase_seg2; ++ int sjw = dbt->sjw; ++ int err; ++ ++ if (!ops->dev_set_data_bittiming || ++ !ops->dev_get_data_busparams) ++ return -EOPNOTSUPP; ++ ++ busparams.bitrate = cpu_to_le32(dbt->bitrate); ++ busparams.sjw = (u8)sjw; ++ busparams.tseg1 = (u8)tseg1; ++ busparams.tseg2 = (u8)tseg2; ++ busparams.nsamples = 1; ++ ++ err = ops->dev_set_data_bittiming(netdev, &busparams); ++ if (err) ++ return err; ++ ++ err = kvaser_usb_setup_rx_urbs(priv->dev); ++ if (err) ++ return err; ++ ++ err = ops->dev_get_data_busparams(priv); ++ if (err) ++ return err; ++ ++ if (memcmp(&busparams, &priv->busparams_data, ++ sizeof(priv->busparams_data)) != 0) ++ err = -EINVAL; ++ ++ return err; ++} ++ + static void kvaser_usb_write_bulk_callback(struct urb *urb) + { + struct kvaser_usb_tx_urb_context *context = urb->context; +@@ -684,6 +767,7 @@ static const struct ethtool_ops kvaser_usb_ethtool_ops_hwts = { + + static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev) + { ++ const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops; + int i; + + for (i = 0; i < dev->nchannels; i++) { +@@ -699,6 +783,9 @@ static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev) + if (!dev->nets[i]) + continue; + ++ if (ops->dev_remove_channel) ++ ops->dev_remove_channel(dev->nets[i]); ++ + free_candev(dev->nets[i]->netdev); + } + } +@@ -730,6 +817,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel) + init_completion(&priv->start_comp); + init_completion(&priv->stop_comp); + init_completion(&priv->flush_comp); ++ init_completion(&priv->get_busparams_comp); + priv->can.ctrlmode_supported = 0; + + priv->dev = dev; +@@ -742,7 +830,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel) + priv->can.state = CAN_STATE_STOPPED; + priv->can.clock.freq = dev->cfg->clock.freq; + priv->can.bittiming_const = dev->cfg->bittiming_const; +- priv->can.do_set_bittiming = ops->dev_set_bittiming; ++ priv->can.do_set_bittiming = kvaser_usb_set_bittiming; + priv->can.do_set_mode = ops->dev_set_mode; + if ((driver_info->quirks & KVASER_USB_QUIRK_HAS_TXRX_ERRORS) || + (priv->dev->card_data.capabilities & KVASER_USB_CAP_BERR_CAP)) +@@ -754,7 +842,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel) + + if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) { + priv->can.data_bittiming_const = dev->cfg->data_bittiming_const; +- priv->can.do_set_data_bittiming = ops->dev_set_data_bittiming; ++ priv->can.do_set_data_bittiming = kvaser_usb_set_data_bittiming; + } + + netdev->flags |= IFF_ECHO; +@@ -772,17 +860,26 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel) + + dev->nets[channel] = priv; + ++ if (ops->dev_init_channel) { ++ err = ops->dev_init_channel(priv); ++ if (err) ++ goto err; ++ } ++ + err = register_candev(netdev); + if (err) { + dev_err(&dev->intf->dev, "Failed to register CAN device\n"); +- free_candev(netdev); +- dev->nets[channel] = NULL; +- return err; ++ goto err; + } + + netdev_dbg(netdev, "device registered\n"); + + return 0; ++ ++err: ++ free_candev(netdev); ++ dev->nets[channel] = NULL; ++ return err; + } + + static int kvaser_usb_probe(struct usb_interface *intf, +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +index 66f672ea631b8..f688124d6d669 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +@@ -45,6 +45,8 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_rt; + + /* Minihydra command IDs */ + #define CMD_SET_BUSPARAMS_REQ 16 ++#define CMD_GET_BUSPARAMS_REQ 17 ++#define CMD_GET_BUSPARAMS_RESP 18 + #define CMD_GET_CHIP_STATE_REQ 19 + #define CMD_CHIP_STATE_EVENT 20 + #define CMD_SET_DRIVERMODE_REQ 21 +@@ -196,21 +198,26 @@ struct kvaser_cmd_chip_state_event { + #define KVASER_USB_HYDRA_BUS_MODE_CANFD_ISO 0x01 + #define KVASER_USB_HYDRA_BUS_MODE_NONISO 0x02 + struct kvaser_cmd_set_busparams { +- __le32 bitrate; +- u8 tseg1; +- u8 tseg2; +- u8 sjw; +- u8 nsamples; ++ struct kvaser_usb_busparams busparams_nominal; + u8 reserved0[4]; +- __le32 bitrate_d; +- u8 tseg1_d; +- u8 tseg2_d; +- u8 sjw_d; +- u8 nsamples_d; ++ struct kvaser_usb_busparams busparams_data; + u8 canfd_mode; + u8 reserved1[7]; + } __packed; + ++/* Busparam type */ ++#define KVASER_USB_HYDRA_BUSPARAM_TYPE_CAN 0x00 ++#define KVASER_USB_HYDRA_BUSPARAM_TYPE_CANFD 0x01 ++struct kvaser_cmd_get_busparams_req { ++ u8 type; ++ u8 reserved[27]; ++} __packed; ++ ++struct kvaser_cmd_get_busparams_res { ++ struct kvaser_usb_busparams busparams; ++ u8 reserved[20]; ++} __packed; ++ + /* Ctrl modes */ + #define KVASER_USB_HYDRA_CTRLMODE_NORMAL 0x01 + #define KVASER_USB_HYDRA_CTRLMODE_LISTEN 0x02 +@@ -281,6 +288,8 @@ struct kvaser_cmd { + struct kvaser_cmd_error_event error_event; + + struct kvaser_cmd_set_busparams set_busparams_req; ++ struct kvaser_cmd_get_busparams_req get_busparams_req; ++ struct kvaser_cmd_get_busparams_res get_busparams_res; + + struct kvaser_cmd_chip_state_event chip_state_event; + +@@ -363,6 +372,10 @@ struct kvaser_cmd_ext { + } __packed; + } __packed; + ++struct kvaser_usb_net_hydra_priv { ++ int pending_get_busparams_type; ++}; ++ + static const struct can_bittiming_const kvaser_usb_hydra_kcan_bittiming_c = { + .name = "kvaser_usb_kcan", + .tseg1_min = 1, +@@ -840,6 +853,39 @@ static void kvaser_usb_hydra_flush_queue_reply(const struct kvaser_usb *dev, + complete(&priv->flush_comp); + } + ++static void kvaser_usb_hydra_get_busparams_reply(const struct kvaser_usb *dev, ++ const struct kvaser_cmd *cmd) ++{ ++ struct kvaser_usb_net_priv *priv; ++ struct kvaser_usb_net_hydra_priv *hydra; ++ ++ priv = kvaser_usb_hydra_net_priv_from_cmd(dev, cmd); ++ if (!priv) ++ return; ++ ++ hydra = priv->sub_priv; ++ if (!hydra) ++ return; ++ ++ switch (hydra->pending_get_busparams_type) { ++ case KVASER_USB_HYDRA_BUSPARAM_TYPE_CAN: ++ memcpy(&priv->busparams_nominal, &cmd->get_busparams_res.busparams, ++ sizeof(priv->busparams_nominal)); ++ break; ++ case KVASER_USB_HYDRA_BUSPARAM_TYPE_CANFD: ++ memcpy(&priv->busparams_data, &cmd->get_busparams_res.busparams, ++ sizeof(priv->busparams_nominal)); ++ break; ++ default: ++ dev_warn(&dev->intf->dev, "Unknown get_busparams_type %d\n", ++ hydra->pending_get_busparams_type); ++ break; ++ } ++ hydra->pending_get_busparams_type = -1; ++ ++ complete(&priv->get_busparams_comp); ++} ++ + static void + kvaser_usb_hydra_bus_status_to_can_state(const struct kvaser_usb_net_priv *priv, + u8 bus_status, +@@ -1326,6 +1372,10 @@ static void kvaser_usb_hydra_handle_cmd_std(const struct kvaser_usb *dev, + kvaser_usb_hydra_state_event(dev, cmd); + break; + ++ case CMD_GET_BUSPARAMS_RESP: ++ kvaser_usb_hydra_get_busparams_reply(dev, cmd); ++ break; ++ + case CMD_ERROR_EVENT: + kvaser_usb_hydra_error_event(dev, cmd); + break; +@@ -1522,15 +1572,58 @@ static int kvaser_usb_hydra_set_mode(struct net_device *netdev, + return err; + } + +-static int kvaser_usb_hydra_set_bittiming(struct net_device *netdev) ++static int kvaser_usb_hydra_get_busparams(struct kvaser_usb_net_priv *priv, ++ int busparams_type) ++{ ++ struct kvaser_usb *dev = priv->dev; ++ struct kvaser_usb_net_hydra_priv *hydra = priv->sub_priv; ++ struct kvaser_cmd *cmd; ++ int err; ++ ++ if (!hydra) ++ return -EINVAL; ++ ++ cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL); ++ if (!cmd) ++ return -ENOMEM; ++ ++ cmd->header.cmd_no = CMD_GET_BUSPARAMS_REQ; ++ kvaser_usb_hydra_set_cmd_dest_he ++ (cmd, dev->card_data.hydra.channel_to_he[priv->channel]); ++ kvaser_usb_hydra_set_cmd_transid ++ (cmd, kvaser_usb_hydra_get_next_transid(dev)); ++ cmd->get_busparams_req.type = busparams_type; ++ hydra->pending_get_busparams_type = busparams_type; ++ ++ reinit_completion(&priv->get_busparams_comp); ++ ++ err = kvaser_usb_send_cmd(dev, cmd, kvaser_usb_hydra_cmd_size(cmd)); ++ if (err) ++ return err; ++ ++ if (!wait_for_completion_timeout(&priv->get_busparams_comp, ++ msecs_to_jiffies(KVASER_USB_TIMEOUT))) ++ return -ETIMEDOUT; ++ ++ return err; ++} ++ ++static int kvaser_usb_hydra_get_nominal_busparams(struct kvaser_usb_net_priv *priv) ++{ ++ return kvaser_usb_hydra_get_busparams(priv, KVASER_USB_HYDRA_BUSPARAM_TYPE_CAN); ++} ++ ++static int kvaser_usb_hydra_get_data_busparams(struct kvaser_usb_net_priv *priv) ++{ ++ return kvaser_usb_hydra_get_busparams(priv, KVASER_USB_HYDRA_BUSPARAM_TYPE_CANFD); ++} ++ ++static int kvaser_usb_hydra_set_bittiming(const struct net_device *netdev, ++ const struct kvaser_usb_busparams *busparams) + { + struct kvaser_cmd *cmd; + struct kvaser_usb_net_priv *priv = netdev_priv(netdev); +- struct can_bittiming *bt = &priv->can.bittiming; + struct kvaser_usb *dev = priv->dev; +- int tseg1 = bt->prop_seg + bt->phase_seg1; +- int tseg2 = bt->phase_seg2; +- int sjw = bt->sjw; + int err; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); +@@ -1538,11 +1631,8 @@ static int kvaser_usb_hydra_set_bittiming(struct net_device *netdev) + return -ENOMEM; + + cmd->header.cmd_no = CMD_SET_BUSPARAMS_REQ; +- cmd->set_busparams_req.bitrate = cpu_to_le32(bt->bitrate); +- cmd->set_busparams_req.sjw = (u8)sjw; +- cmd->set_busparams_req.tseg1 = (u8)tseg1; +- cmd->set_busparams_req.tseg2 = (u8)tseg2; +- cmd->set_busparams_req.nsamples = 1; ++ memcpy(&cmd->set_busparams_req.busparams_nominal, busparams, ++ sizeof(cmd->set_busparams_req.busparams_nominal)); + + kvaser_usb_hydra_set_cmd_dest_he + (cmd, dev->card_data.hydra.channel_to_he[priv->channel]); +@@ -1556,15 +1646,12 @@ static int kvaser_usb_hydra_set_bittiming(struct net_device *netdev) + return err; + } + +-static int kvaser_usb_hydra_set_data_bittiming(struct net_device *netdev) ++static int kvaser_usb_hydra_set_data_bittiming(const struct net_device *netdev, ++ const struct kvaser_usb_busparams *busparams) + { + struct kvaser_cmd *cmd; + struct kvaser_usb_net_priv *priv = netdev_priv(netdev); +- struct can_bittiming *dbt = &priv->can.data_bittiming; + struct kvaser_usb *dev = priv->dev; +- int tseg1 = dbt->prop_seg + dbt->phase_seg1; +- int tseg2 = dbt->phase_seg2; +- int sjw = dbt->sjw; + int err; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); +@@ -1572,11 +1659,8 @@ static int kvaser_usb_hydra_set_data_bittiming(struct net_device *netdev) + return -ENOMEM; + + cmd->header.cmd_no = CMD_SET_BUSPARAMS_FD_REQ; +- cmd->set_busparams_req.bitrate_d = cpu_to_le32(dbt->bitrate); +- cmd->set_busparams_req.sjw_d = (u8)sjw; +- cmd->set_busparams_req.tseg1_d = (u8)tseg1; +- cmd->set_busparams_req.tseg2_d = (u8)tseg2; +- cmd->set_busparams_req.nsamples_d = 1; ++ memcpy(&cmd->set_busparams_req.busparams_data, busparams, ++ sizeof(cmd->set_busparams_req.busparams_data)); + + if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { + if (priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO) +@@ -1683,6 +1767,19 @@ static int kvaser_usb_hydra_init_card(struct kvaser_usb *dev) + return 0; + } + ++static int kvaser_usb_hydra_init_channel(struct kvaser_usb_net_priv *priv) ++{ ++ struct kvaser_usb_net_hydra_priv *hydra; ++ ++ hydra = devm_kzalloc(&priv->dev->intf->dev, sizeof(*hydra), GFP_KERNEL); ++ if (!hydra) ++ return -ENOMEM; ++ ++ priv->sub_priv = hydra; ++ ++ return 0; ++} ++ + static int kvaser_usb_hydra_get_software_info(struct kvaser_usb *dev) + { + struct kvaser_cmd cmd; +@@ -2027,10 +2124,13 @@ kvaser_usb_hydra_frame_to_cmd(const struct kvaser_usb_net_priv *priv, + const struct kvaser_usb_dev_ops kvaser_usb_hydra_dev_ops = { + .dev_set_mode = kvaser_usb_hydra_set_mode, + .dev_set_bittiming = kvaser_usb_hydra_set_bittiming, ++ .dev_get_busparams = kvaser_usb_hydra_get_nominal_busparams, + .dev_set_data_bittiming = kvaser_usb_hydra_set_data_bittiming, ++ .dev_get_data_busparams = kvaser_usb_hydra_get_data_busparams, + .dev_get_berr_counter = kvaser_usb_hydra_get_berr_counter, + .dev_setup_endpoints = kvaser_usb_hydra_setup_endpoints, + .dev_init_card = kvaser_usb_hydra_init_card, ++ .dev_init_channel = kvaser_usb_hydra_init_channel, + .dev_get_software_info = kvaser_usb_hydra_get_software_info, + .dev_get_software_details = kvaser_usb_hydra_get_software_details, + .dev_get_card_info = kvaser_usb_hydra_get_card_info, +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 19958037720f4..b423fd4c79890 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -21,6 +21,7 @@ + #include <linux/types.h> + #include <linux/units.h> + #include <linux/usb.h> ++#include <linux/workqueue.h> + + #include <linux/can.h> + #include <linux/can/dev.h> +@@ -56,6 +57,9 @@ + #define CMD_RX_EXT_MESSAGE 14 + #define CMD_TX_EXT_MESSAGE 15 + #define CMD_SET_BUS_PARAMS 16 ++#define CMD_GET_BUS_PARAMS 17 ++#define CMD_GET_BUS_PARAMS_REPLY 18 ++#define CMD_GET_CHIP_STATE 19 + #define CMD_CHIP_STATE_EVENT 20 + #define CMD_SET_CTRL_MODE 21 + #define CMD_RESET_CHIP 24 +@@ -70,10 +74,13 @@ + #define CMD_GET_CARD_INFO_REPLY 35 + #define CMD_GET_SOFTWARE_INFO 38 + #define CMD_GET_SOFTWARE_INFO_REPLY 39 ++#define CMD_ERROR_EVENT 45 + #define CMD_FLUSH_QUEUE 48 + #define CMD_TX_ACKNOWLEDGE 50 + #define CMD_CAN_ERROR_EVENT 51 + #define CMD_FLUSH_QUEUE_REPLY 68 ++#define CMD_GET_CAPABILITIES_REQ 95 ++#define CMD_GET_CAPABILITIES_RESP 96 + + #define CMD_LEAF_LOG_MESSAGE 106 + +@@ -83,6 +90,8 @@ + #define KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK BIT(5) + #define KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK BIT(6) + ++#define KVASER_USB_LEAF_SWOPTION_EXT_CAP BIT(12) ++ + /* error factors */ + #define M16C_EF_ACKE BIT(0) + #define M16C_EF_CRCE BIT(1) +@@ -157,11 +166,7 @@ struct usbcan_cmd_softinfo { + struct kvaser_cmd_busparams { + u8 tid; + u8 channel; +- __le32 bitrate; +- u8 tseg1; +- u8 tseg2; +- u8 sjw; +- u8 no_samp; ++ struct kvaser_usb_busparams busparams; + } __packed; + + struct kvaser_cmd_tx_can { +@@ -230,7 +235,7 @@ struct kvaser_cmd_tx_acknowledge_header { + u8 tid; + } __packed; + +-struct leaf_cmd_error_event { ++struct leaf_cmd_can_error_event { + u8 tid; + u8 flags; + __le16 time[3]; +@@ -242,7 +247,7 @@ struct leaf_cmd_error_event { + u8 error_factor; + } __packed; + +-struct usbcan_cmd_error_event { ++struct usbcan_cmd_can_error_event { + u8 tid; + u8 padding; + u8 tx_errors_count_ch0; +@@ -254,6 +259,28 @@ struct usbcan_cmd_error_event { + __le16 time; + } __packed; + ++/* CMD_ERROR_EVENT error codes */ ++#define KVASER_USB_LEAF_ERROR_EVENT_TX_QUEUE_FULL 0x8 ++#define KVASER_USB_LEAF_ERROR_EVENT_PARAM 0x9 ++ ++struct leaf_cmd_error_event { ++ u8 tid; ++ u8 error_code; ++ __le16 timestamp[3]; ++ __le16 padding; ++ __le16 info1; ++ __le16 info2; ++} __packed; ++ ++struct usbcan_cmd_error_event { ++ u8 tid; ++ u8 error_code; ++ __le16 info1; ++ __le16 info2; ++ __le16 timestamp; ++ __le16 padding; ++} __packed; ++ + struct kvaser_cmd_ctrl_mode { + u8 tid; + u8 channel; +@@ -278,6 +305,28 @@ struct leaf_cmd_log_message { + u8 data[8]; + } __packed; + ++/* Sub commands for cap_req and cap_res */ ++#define KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE 0x02 ++#define KVASER_USB_LEAF_CAP_CMD_ERR_REPORT 0x05 ++struct kvaser_cmd_cap_req { ++ __le16 padding0; ++ __le16 cap_cmd; ++ __le16 padding1; ++ __le16 channel; ++} __packed; ++ ++/* Status codes for cap_res */ ++#define KVASER_USB_LEAF_CAP_STAT_OK 0x00 ++#define KVASER_USB_LEAF_CAP_STAT_NOT_IMPL 0x01 ++#define KVASER_USB_LEAF_CAP_STAT_UNAVAIL 0x02 ++struct kvaser_cmd_cap_res { ++ __le16 padding; ++ __le16 cap_cmd; ++ __le16 status; ++ __le32 mask; ++ __le32 value; ++} __packed; ++ + struct kvaser_cmd { + u8 len; + u8 id; +@@ -293,14 +342,18 @@ struct kvaser_cmd { + struct leaf_cmd_softinfo softinfo; + struct leaf_cmd_rx_can rx_can; + struct leaf_cmd_chip_state_event chip_state_event; +- struct leaf_cmd_error_event error_event; ++ struct leaf_cmd_can_error_event can_error_event; + struct leaf_cmd_log_message log_message; ++ struct leaf_cmd_error_event error_event; ++ struct kvaser_cmd_cap_req cap_req; ++ struct kvaser_cmd_cap_res cap_res; + } __packed leaf; + + union { + struct usbcan_cmd_softinfo softinfo; + struct usbcan_cmd_rx_can rx_can; + struct usbcan_cmd_chip_state_event chip_state_event; ++ struct usbcan_cmd_can_error_event can_error_event; + struct usbcan_cmd_error_event error_event; + } __packed usbcan; + +@@ -323,7 +376,10 @@ static const u8 kvaser_usb_leaf_cmd_sizes_leaf[] = { + [CMD_RX_EXT_MESSAGE] = kvaser_fsize(u.leaf.rx_can), + [CMD_LEAF_LOG_MESSAGE] = kvaser_fsize(u.leaf.log_message), + [CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.leaf.chip_state_event), +- [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.leaf.error_event), ++ [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.leaf.can_error_event), ++ [CMD_GET_CAPABILITIES_RESP] = kvaser_fsize(u.leaf.cap_res), ++ [CMD_GET_BUS_PARAMS_REPLY] = kvaser_fsize(u.busparams), ++ [CMD_ERROR_EVENT] = kvaser_fsize(u.leaf.error_event), + /* ignored events: */ + [CMD_FLUSH_QUEUE_REPLY] = CMD_SIZE_ANY, + }; +@@ -337,7 +393,8 @@ static const u8 kvaser_usb_leaf_cmd_sizes_usbcan[] = { + [CMD_RX_STD_MESSAGE] = kvaser_fsize(u.usbcan.rx_can), + [CMD_RX_EXT_MESSAGE] = kvaser_fsize(u.usbcan.rx_can), + [CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.usbcan.chip_state_event), +- [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.usbcan.error_event), ++ [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.usbcan.can_error_event), ++ [CMD_ERROR_EVENT] = kvaser_fsize(u.usbcan.error_event), + /* ignored events: */ + [CMD_USBCAN_CLOCK_OVERFLOW_EVENT] = CMD_SIZE_ANY, + }; +@@ -365,6 +422,12 @@ struct kvaser_usb_err_summary { + }; + }; + ++struct kvaser_usb_net_leaf_priv { ++ struct kvaser_usb_net_priv *net; ++ ++ struct delayed_work chip_state_req_work; ++}; ++ + static const struct can_bittiming_const kvaser_usb_leaf_m16c_bittiming_const = { + .name = "kvaser_usb_ucii", + .tseg1_min = 4, +@@ -606,6 +669,9 @@ static void kvaser_usb_leaf_get_software_info_leaf(struct kvaser_usb *dev, + dev->fw_version = le32_to_cpu(softinfo->fw_version); + dev->max_tx_urbs = le16_to_cpu(softinfo->max_outstanding_tx); + ++ if (sw_options & KVASER_USB_LEAF_SWOPTION_EXT_CAP) ++ dev->card_data.capabilities |= KVASER_USB_CAP_EXT_CAP; ++ + if (dev->driver_info->quirks & KVASER_USB_QUIRK_IGNORE_CLK_FREQ) { + /* Firmware expects bittiming parameters calculated for 16MHz + * clock, regardless of the actual clock +@@ -693,6 +759,116 @@ static int kvaser_usb_leaf_get_card_info(struct kvaser_usb *dev) + return 0; + } + ++static int kvaser_usb_leaf_get_single_capability(struct kvaser_usb *dev, ++ u16 cap_cmd_req, u16 *status) ++{ ++ struct kvaser_usb_dev_card_data *card_data = &dev->card_data; ++ struct kvaser_cmd *cmd; ++ u32 value = 0; ++ u32 mask = 0; ++ u16 cap_cmd_res; ++ int err; ++ int i; ++ ++ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); ++ if (!cmd) ++ return -ENOMEM; ++ ++ cmd->id = CMD_GET_CAPABILITIES_REQ; ++ cmd->u.leaf.cap_req.cap_cmd = cpu_to_le16(cap_cmd_req); ++ cmd->len = CMD_HEADER_LEN + sizeof(struct kvaser_cmd_cap_req); ++ ++ err = kvaser_usb_send_cmd(dev, cmd, cmd->len); ++ if (err) ++ goto end; ++ ++ err = kvaser_usb_leaf_wait_cmd(dev, CMD_GET_CAPABILITIES_RESP, cmd); ++ if (err) ++ goto end; ++ ++ *status = le16_to_cpu(cmd->u.leaf.cap_res.status); ++ ++ if (*status != KVASER_USB_LEAF_CAP_STAT_OK) ++ goto end; ++ ++ cap_cmd_res = le16_to_cpu(cmd->u.leaf.cap_res.cap_cmd); ++ switch (cap_cmd_res) { ++ case KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE: ++ case KVASER_USB_LEAF_CAP_CMD_ERR_REPORT: ++ value = le32_to_cpu(cmd->u.leaf.cap_res.value); ++ mask = le32_to_cpu(cmd->u.leaf.cap_res.mask); ++ break; ++ default: ++ dev_warn(&dev->intf->dev, "Unknown capability command %u\n", ++ cap_cmd_res); ++ break; ++ } ++ ++ for (i = 0; i < dev->nchannels; i++) { ++ if (BIT(i) & (value & mask)) { ++ switch (cap_cmd_res) { ++ case KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE: ++ card_data->ctrlmode_supported |= ++ CAN_CTRLMODE_LISTENONLY; ++ break; ++ case KVASER_USB_LEAF_CAP_CMD_ERR_REPORT: ++ card_data->capabilities |= ++ KVASER_USB_CAP_BERR_CAP; ++ break; ++ } ++ } ++ } ++ ++end: ++ kfree(cmd); ++ ++ return err; ++} ++ ++static int kvaser_usb_leaf_get_capabilities_leaf(struct kvaser_usb *dev) ++{ ++ int err; ++ u16 status; ++ ++ if (!(dev->card_data.capabilities & KVASER_USB_CAP_EXT_CAP)) { ++ dev_info(&dev->intf->dev, ++ "No extended capability support. Upgrade device firmware.\n"); ++ return 0; ++ } ++ ++ err = kvaser_usb_leaf_get_single_capability(dev, ++ KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE, ++ &status); ++ if (err) ++ return err; ++ if (status) ++ dev_info(&dev->intf->dev, ++ "KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE failed %u\n", ++ status); ++ ++ err = kvaser_usb_leaf_get_single_capability(dev, ++ KVASER_USB_LEAF_CAP_CMD_ERR_REPORT, ++ &status); ++ if (err) ++ return err; ++ if (status) ++ dev_info(&dev->intf->dev, ++ "KVASER_USB_LEAF_CAP_CMD_ERR_REPORT failed %u\n", ++ status); ++ ++ return 0; ++} ++ ++static int kvaser_usb_leaf_get_capabilities(struct kvaser_usb *dev) ++{ ++ int err = 0; ++ ++ if (dev->driver_info->family == KVASER_LEAF) ++ err = kvaser_usb_leaf_get_capabilities_leaf(dev); ++ ++ return err; ++} ++ + static void kvaser_usb_leaf_tx_acknowledge(const struct kvaser_usb *dev, + const struct kvaser_cmd *cmd) + { +@@ -721,7 +897,7 @@ static void kvaser_usb_leaf_tx_acknowledge(const struct kvaser_usb *dev, + context = &priv->tx_contexts[tid % dev->max_tx_urbs]; + + /* Sometimes the state change doesn't come after a bus-off event */ +- if (priv->can.restart_ms && priv->can.state >= CAN_STATE_BUS_OFF) { ++ if (priv->can.restart_ms && priv->can.state == CAN_STATE_BUS_OFF) { + struct sk_buff *skb; + struct can_frame *cf; + +@@ -774,6 +950,16 @@ static int kvaser_usb_leaf_simple_cmd_async(struct kvaser_usb_net_priv *priv, + return err; + } + ++static void kvaser_usb_leaf_chip_state_req_work(struct work_struct *work) ++{ ++ struct kvaser_usb_net_leaf_priv *leaf = ++ container_of(work, struct kvaser_usb_net_leaf_priv, ++ chip_state_req_work.work); ++ struct kvaser_usb_net_priv *priv = leaf->net; ++ ++ kvaser_usb_leaf_simple_cmd_async(priv, CMD_GET_CHIP_STATE); ++} ++ + static void + kvaser_usb_leaf_rx_error_update_can_state(struct kvaser_usb_net_priv *priv, + const struct kvaser_usb_err_summary *es, +@@ -792,20 +978,16 @@ kvaser_usb_leaf_rx_error_update_can_state(struct kvaser_usb_net_priv *priv, + new_state = CAN_STATE_BUS_OFF; + } else if (es->status & M16C_STATE_BUS_PASSIVE) { + new_state = CAN_STATE_ERROR_PASSIVE; +- } else if (es->status & M16C_STATE_BUS_ERROR) { ++ } else if ((es->status & M16C_STATE_BUS_ERROR) && ++ cur_state >= CAN_STATE_BUS_OFF) { + /* Guard against spurious error events after a busoff */ +- if (cur_state < CAN_STATE_BUS_OFF) { +- if (es->txerr >= 128 || es->rxerr >= 128) +- new_state = CAN_STATE_ERROR_PASSIVE; +- else if (es->txerr >= 96 || es->rxerr >= 96) +- new_state = CAN_STATE_ERROR_WARNING; +- else if (cur_state > CAN_STATE_ERROR_ACTIVE) +- new_state = CAN_STATE_ERROR_ACTIVE; +- } +- } +- +- if (!es->status) ++ } else if (es->txerr >= 128 || es->rxerr >= 128) { ++ new_state = CAN_STATE_ERROR_PASSIVE; ++ } else if (es->txerr >= 96 || es->rxerr >= 96) { ++ new_state = CAN_STATE_ERROR_WARNING; ++ } else { + new_state = CAN_STATE_ERROR_ACTIVE; ++ } + + if (new_state != cur_state) { + tx_state = (es->txerr >= es->rxerr) ? new_state : 0; +@@ -815,7 +997,7 @@ kvaser_usb_leaf_rx_error_update_can_state(struct kvaser_usb_net_priv *priv, + } + + if (priv->can.restart_ms && +- cur_state >= CAN_STATE_BUS_OFF && ++ cur_state == CAN_STATE_BUS_OFF && + new_state < CAN_STATE_BUS_OFF) + priv->can.can_stats.restarts++; + +@@ -849,6 +1031,7 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev, + struct sk_buff *skb; + struct net_device_stats *stats; + struct kvaser_usb_net_priv *priv; ++ struct kvaser_usb_net_leaf_priv *leaf; + enum can_state old_state, new_state; + + if (es->channel >= dev->nchannels) { +@@ -858,8 +1041,13 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev, + } + + priv = dev->nets[es->channel]; ++ leaf = priv->sub_priv; + stats = &priv->netdev->stats; + ++ /* Ignore e.g. state change to bus-off reported just after stopping */ ++ if (!netif_running(priv->netdev)) ++ return; ++ + /* Update all of the CAN interface's state and error counters before + * trying any memory allocation that can actually fail with -ENOMEM. + * +@@ -874,6 +1062,14 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev, + kvaser_usb_leaf_rx_error_update_can_state(priv, es, &tmp_cf); + new_state = priv->can.state; + ++ /* If there are errors, request status updates periodically as we do ++ * not get automatic notifications of improved state. ++ */ ++ if (new_state < CAN_STATE_BUS_OFF && ++ (es->rxerr || es->txerr || new_state == CAN_STATE_ERROR_PASSIVE)) ++ schedule_delayed_work(&leaf->chip_state_req_work, ++ msecs_to_jiffies(500)); ++ + skb = alloc_can_err_skb(priv->netdev, &cf); + if (!skb) { + stats->rx_dropped++; +@@ -891,7 +1087,7 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev, + } + + if (priv->can.restart_ms && +- old_state >= CAN_STATE_BUS_OFF && ++ old_state == CAN_STATE_BUS_OFF && + new_state < CAN_STATE_BUS_OFF) { + cf->can_id |= CAN_ERR_RESTARTED; + netif_carrier_on(priv->netdev); +@@ -990,11 +1186,11 @@ static void kvaser_usb_leaf_usbcan_rx_error(const struct kvaser_usb *dev, + + case CMD_CAN_ERROR_EVENT: + es.channel = 0; +- es.status = cmd->u.usbcan.error_event.status_ch0; +- es.txerr = cmd->u.usbcan.error_event.tx_errors_count_ch0; +- es.rxerr = cmd->u.usbcan.error_event.rx_errors_count_ch0; ++ es.status = cmd->u.usbcan.can_error_event.status_ch0; ++ es.txerr = cmd->u.usbcan.can_error_event.tx_errors_count_ch0; ++ es.rxerr = cmd->u.usbcan.can_error_event.rx_errors_count_ch0; + es.usbcan.other_ch_status = +- cmd->u.usbcan.error_event.status_ch1; ++ cmd->u.usbcan.can_error_event.status_ch1; + kvaser_usb_leaf_usbcan_conditionally_rx_error(dev, &es); + + /* The USBCAN firmware supports up to 2 channels. +@@ -1002,13 +1198,13 @@ static void kvaser_usb_leaf_usbcan_rx_error(const struct kvaser_usb *dev, + */ + if (dev->nchannels == MAX_USBCAN_NET_DEVICES) { + es.channel = 1; +- es.status = cmd->u.usbcan.error_event.status_ch1; ++ es.status = cmd->u.usbcan.can_error_event.status_ch1; + es.txerr = +- cmd->u.usbcan.error_event.tx_errors_count_ch1; ++ cmd->u.usbcan.can_error_event.tx_errors_count_ch1; + es.rxerr = +- cmd->u.usbcan.error_event.rx_errors_count_ch1; ++ cmd->u.usbcan.can_error_event.rx_errors_count_ch1; + es.usbcan.other_ch_status = +- cmd->u.usbcan.error_event.status_ch0; ++ cmd->u.usbcan.can_error_event.status_ch0; + kvaser_usb_leaf_usbcan_conditionally_rx_error(dev, &es); + } + break; +@@ -1025,11 +1221,11 @@ static void kvaser_usb_leaf_leaf_rx_error(const struct kvaser_usb *dev, + + switch (cmd->id) { + case CMD_CAN_ERROR_EVENT: +- es.channel = cmd->u.leaf.error_event.channel; +- es.status = cmd->u.leaf.error_event.status; +- es.txerr = cmd->u.leaf.error_event.tx_errors_count; +- es.rxerr = cmd->u.leaf.error_event.rx_errors_count; +- es.leaf.error_factor = cmd->u.leaf.error_event.error_factor; ++ es.channel = cmd->u.leaf.can_error_event.channel; ++ es.status = cmd->u.leaf.can_error_event.status; ++ es.txerr = cmd->u.leaf.can_error_event.tx_errors_count; ++ es.rxerr = cmd->u.leaf.can_error_event.rx_errors_count; ++ es.leaf.error_factor = cmd->u.leaf.can_error_event.error_factor; + break; + case CMD_LEAF_LOG_MESSAGE: + es.channel = cmd->u.leaf.log_message.channel; +@@ -1162,6 +1358,74 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev, + netif_rx(skb); + } + ++static void kvaser_usb_leaf_error_event_parameter(const struct kvaser_usb *dev, ++ const struct kvaser_cmd *cmd) ++{ ++ u16 info1 = 0; ++ ++ switch (dev->driver_info->family) { ++ case KVASER_LEAF: ++ info1 = le16_to_cpu(cmd->u.leaf.error_event.info1); ++ break; ++ case KVASER_USBCAN: ++ info1 = le16_to_cpu(cmd->u.usbcan.error_event.info1); ++ break; ++ } ++ ++ /* info1 will contain the offending cmd_no */ ++ switch (info1) { ++ case CMD_SET_CTRL_MODE: ++ dev_warn(&dev->intf->dev, ++ "CMD_SET_CTRL_MODE error in parameter\n"); ++ break; ++ ++ case CMD_SET_BUS_PARAMS: ++ dev_warn(&dev->intf->dev, ++ "CMD_SET_BUS_PARAMS error in parameter\n"); ++ break; ++ ++ default: ++ dev_warn(&dev->intf->dev, ++ "Unhandled parameter error event cmd_no (%u)\n", ++ info1); ++ break; ++ } ++} ++ ++static void kvaser_usb_leaf_error_event(const struct kvaser_usb *dev, ++ const struct kvaser_cmd *cmd) ++{ ++ u8 error_code = 0; ++ ++ switch (dev->driver_info->family) { ++ case KVASER_LEAF: ++ error_code = cmd->u.leaf.error_event.error_code; ++ break; ++ case KVASER_USBCAN: ++ error_code = cmd->u.usbcan.error_event.error_code; ++ break; ++ } ++ ++ switch (error_code) { ++ case KVASER_USB_LEAF_ERROR_EVENT_TX_QUEUE_FULL: ++ /* Received additional CAN message, when firmware TX queue is ++ * already full. Something is wrong with the driver. ++ * This should never happen! ++ */ ++ dev_err(&dev->intf->dev, ++ "Received error event TX_QUEUE_FULL\n"); ++ break; ++ case KVASER_USB_LEAF_ERROR_EVENT_PARAM: ++ kvaser_usb_leaf_error_event_parameter(dev, cmd); ++ break; ++ ++ default: ++ dev_warn(&dev->intf->dev, ++ "Unhandled error event (%d)\n", error_code); ++ break; ++ } ++} ++ + static void kvaser_usb_leaf_start_chip_reply(const struct kvaser_usb *dev, + const struct kvaser_cmd *cmd) + { +@@ -1202,6 +1466,25 @@ static void kvaser_usb_leaf_stop_chip_reply(const struct kvaser_usb *dev, + complete(&priv->stop_comp); + } + ++static void kvaser_usb_leaf_get_busparams_reply(const struct kvaser_usb *dev, ++ const struct kvaser_cmd *cmd) ++{ ++ struct kvaser_usb_net_priv *priv; ++ u8 channel = cmd->u.busparams.channel; ++ ++ if (channel >= dev->nchannels) { ++ dev_err(&dev->intf->dev, ++ "Invalid channel number (%d)\n", channel); ++ return; ++ } ++ ++ priv = dev->nets[channel]; ++ memcpy(&priv->busparams_nominal, &cmd->u.busparams.busparams, ++ sizeof(priv->busparams_nominal)); ++ ++ complete(&priv->get_busparams_comp); ++} ++ + static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev, + const struct kvaser_cmd *cmd) + { +@@ -1240,6 +1523,14 @@ static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev, + kvaser_usb_leaf_tx_acknowledge(dev, cmd); + break; + ++ case CMD_ERROR_EVENT: ++ kvaser_usb_leaf_error_event(dev, cmd); ++ break; ++ ++ case CMD_GET_BUS_PARAMS_REPLY: ++ kvaser_usb_leaf_get_busparams_reply(dev, cmd); ++ break; ++ + /* Ignored commands */ + case CMD_USBCAN_CLOCK_OVERFLOW_EVENT: + if (dev->driver_info->family != KVASER_USBCAN) +@@ -1336,10 +1627,13 @@ static int kvaser_usb_leaf_start_chip(struct kvaser_usb_net_priv *priv) + + static int kvaser_usb_leaf_stop_chip(struct kvaser_usb_net_priv *priv) + { ++ struct kvaser_usb_net_leaf_priv *leaf = priv->sub_priv; + int err; + + reinit_completion(&priv->stop_comp); + ++ cancel_delayed_work(&leaf->chip_state_req_work); ++ + err = kvaser_usb_leaf_send_simple_cmd(priv->dev, CMD_STOP_CHIP, + priv->channel); + if (err) +@@ -1386,10 +1680,35 @@ static int kvaser_usb_leaf_init_card(struct kvaser_usb *dev) + return 0; + } + +-static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev) ++static int kvaser_usb_leaf_init_channel(struct kvaser_usb_net_priv *priv) ++{ ++ struct kvaser_usb_net_leaf_priv *leaf; ++ ++ leaf = devm_kzalloc(&priv->dev->intf->dev, sizeof(*leaf), GFP_KERNEL); ++ if (!leaf) ++ return -ENOMEM; ++ ++ leaf->net = priv; ++ INIT_DELAYED_WORK(&leaf->chip_state_req_work, ++ kvaser_usb_leaf_chip_state_req_work); ++ ++ priv->sub_priv = leaf; ++ ++ return 0; ++} ++ ++static void kvaser_usb_leaf_remove_channel(struct kvaser_usb_net_priv *priv) ++{ ++ struct kvaser_usb_net_leaf_priv *leaf = priv->sub_priv; ++ ++ if (leaf) ++ cancel_delayed_work_sync(&leaf->chip_state_req_work); ++} ++ ++static int kvaser_usb_leaf_set_bittiming(const struct net_device *netdev, ++ const struct kvaser_usb_busparams *busparams) + { + struct kvaser_usb_net_priv *priv = netdev_priv(netdev); +- struct can_bittiming *bt = &priv->can.bittiming; + struct kvaser_usb *dev = priv->dev; + struct kvaser_cmd *cmd; + int rc; +@@ -1402,15 +1721,8 @@ static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev) + cmd->len = CMD_HEADER_LEN + sizeof(struct kvaser_cmd_busparams); + cmd->u.busparams.channel = priv->channel; + cmd->u.busparams.tid = 0xff; +- cmd->u.busparams.bitrate = cpu_to_le32(bt->bitrate); +- cmd->u.busparams.sjw = bt->sjw; +- cmd->u.busparams.tseg1 = bt->prop_seg + bt->phase_seg1; +- cmd->u.busparams.tseg2 = bt->phase_seg2; +- +- if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) +- cmd->u.busparams.no_samp = 3; +- else +- cmd->u.busparams.no_samp = 1; ++ memcpy(&cmd->u.busparams.busparams, busparams, ++ sizeof(cmd->u.busparams.busparams)); + + rc = kvaser_usb_send_cmd(dev, cmd, cmd->len); + +@@ -1418,6 +1730,27 @@ static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev) + return rc; + } + ++static int kvaser_usb_leaf_get_busparams(struct kvaser_usb_net_priv *priv) ++{ ++ int err; ++ ++ if (priv->dev->driver_info->family == KVASER_USBCAN) ++ return -EOPNOTSUPP; ++ ++ reinit_completion(&priv->get_busparams_comp); ++ ++ err = kvaser_usb_leaf_send_simple_cmd(priv->dev, CMD_GET_BUS_PARAMS, ++ priv->channel); ++ if (err) ++ return err; ++ ++ if (!wait_for_completion_timeout(&priv->get_busparams_comp, ++ msecs_to_jiffies(KVASER_USB_TIMEOUT))) ++ return -ETIMEDOUT; ++ ++ return 0; ++} ++ + static int kvaser_usb_leaf_set_mode(struct net_device *netdev, + enum can_mode mode) + { +@@ -1479,14 +1812,18 @@ static int kvaser_usb_leaf_setup_endpoints(struct kvaser_usb *dev) + const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = { + .dev_set_mode = kvaser_usb_leaf_set_mode, + .dev_set_bittiming = kvaser_usb_leaf_set_bittiming, ++ .dev_get_busparams = kvaser_usb_leaf_get_busparams, + .dev_set_data_bittiming = NULL, ++ .dev_get_data_busparams = NULL, + .dev_get_berr_counter = kvaser_usb_leaf_get_berr_counter, + .dev_setup_endpoints = kvaser_usb_leaf_setup_endpoints, + .dev_init_card = kvaser_usb_leaf_init_card, ++ .dev_init_channel = kvaser_usb_leaf_init_channel, ++ .dev_remove_channel = kvaser_usb_leaf_remove_channel, + .dev_get_software_info = kvaser_usb_leaf_get_software_info, + .dev_get_software_details = NULL, + .dev_get_card_info = kvaser_usb_leaf_get_card_info, +- .dev_get_capabilities = NULL, ++ .dev_get_capabilities = kvaser_usb_leaf_get_capabilities, + .dev_set_opt_mode = kvaser_usb_leaf_set_opt_mode, + .dev_start_chip = kvaser_usb_leaf_start_chip, + .dev_stop_chip = kvaser_usb_leaf_stop_chip, +diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c +index 80f07bd205934..2e270b4791432 100644 +--- a/drivers/net/dsa/lan9303-core.c ++++ b/drivers/net/dsa/lan9303-core.c +@@ -1005,9 +1005,11 @@ static void lan9303_get_ethtool_stats(struct dsa_switch *ds, int port, + ret = lan9303_read_switch_port( + chip, port, lan9303_mib[u].offset, ®); + +- if (ret) ++ if (ret) { + dev_warn(chip->dev, "Reading status port %d reg %u failed\n", + port, lan9303_mib[u].offset); ++ reg = 0; ++ } + data[u] = reg; + } + } +diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c +index d612181b3226e..c68f48cd1ec08 100644 +--- a/drivers/net/dsa/microchip/ksz_common.c ++++ b/drivers/net/dsa/microchip/ksz_common.c +@@ -1883,8 +1883,7 @@ static int ksz_irq_common_setup(struct ksz_device *dev, struct ksz_irq *kirq) + irq_create_mapping(kirq->domain, n); + + ret = request_threaded_irq(kirq->irq_num, NULL, ksz_irq_thread_fn, +- IRQF_ONESHOT | IRQF_TRIGGER_FALLING, +- kirq->name, kirq); ++ IRQF_ONESHOT, kirq->name, kirq); + if (ret) + goto out; + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index 937cb22cb3d48..3b8b2d0fbafaf 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -689,13 +689,12 @@ static void mv88e6352_phylink_get_caps(struct mv88e6xxx_chip *chip, int port, + + /* Port 4 supports automedia if the serdes is associated with it. */ + if (port == 4) { +- mv88e6xxx_reg_lock(chip); + err = mv88e6352_g2_scratch_port_has_serdes(chip, port); + if (err < 0) + dev_err(chip->dev, "p%d: failed to read scratch\n", + port); + if (err <= 0) +- goto unlock; ++ return; + + cmode = mv88e6352_get_port4_serdes_cmode(chip); + if (cmode < 0) +@@ -703,8 +702,6 @@ static void mv88e6352_phylink_get_caps(struct mv88e6xxx_chip *chip, int port, + port); + else + mv88e6xxx_translate_cmode(cmode, supported); +-unlock: +- mv88e6xxx_reg_unlock(chip); + } + } + +@@ -831,7 +828,9 @@ static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port, + { + struct mv88e6xxx_chip *chip = ds->priv; + ++ mv88e6xxx_reg_lock(chip); + chip->info->ops->phylink_get_caps(chip, port, config); ++ mv88e6xxx_reg_unlock(chip); + + if (mv88e6xxx_phy_is_internal(ds, port)) { + __set_bit(PHY_INTERFACE_MODE_INTERNAL, +@@ -3307,7 +3306,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) + struct phylink_config pl_config = {}; + unsigned long caps; + +- mv88e6xxx_get_caps(ds, port, &pl_config); ++ chip->info->ops->phylink_get_caps(chip, port, &pl_config); + + caps = pl_config.mac_capabilities; + +diff --git a/drivers/net/ethernet/adi/adin1110.c b/drivers/net/ethernet/adi/adin1110.c +index 606c976108085..9d8dfe1729948 100644 +--- a/drivers/net/ethernet/adi/adin1110.c ++++ b/drivers/net/ethernet/adi/adin1110.c +@@ -196,7 +196,7 @@ static int adin1110_read_reg(struct adin1110_priv *priv, u16 reg, u32 *val) + { + u32 header_len = ADIN1110_RD_HEADER_LEN; + u32 read_len = ADIN1110_REG_LEN; +- struct spi_transfer t[2] = {0}; ++ struct spi_transfer t = {0}; + int ret; + + priv->data[0] = ADIN1110_CD | FIELD_GET(GENMASK(12, 8), reg); +@@ -209,17 +209,15 @@ static int adin1110_read_reg(struct adin1110_priv *priv, u16 reg, u32 *val) + header_len++; + } + +- t[0].tx_buf = &priv->data[0]; +- t[0].len = header_len; +- + if (priv->append_crc) + read_len++; + + memset(&priv->data[header_len], 0, read_len); +- t[1].rx_buf = &priv->data[header_len]; +- t[1].len = read_len; ++ t.tx_buf = &priv->data[0]; ++ t.rx_buf = &priv->data[0]; ++ t.len = read_len + header_len; + +- ret = spi_sync_transfer(priv->spidev, t, 2); ++ ret = spi_sync_transfer(priv->spidev, &t, 1); + if (ret) + return ret; + +@@ -296,7 +294,7 @@ static int adin1110_read_fifo(struct adin1110_port_priv *port_priv) + { + struct adin1110_priv *priv = port_priv->priv; + u32 header_len = ADIN1110_RD_HEADER_LEN; +- struct spi_transfer t[2] = {0}; ++ struct spi_transfer t; + u32 frame_size_no_fcs; + struct sk_buff *rxb; + u32 frame_size; +@@ -327,12 +325,7 @@ static int adin1110_read_fifo(struct adin1110_port_priv *port_priv) + return ret; + + frame_size_no_fcs = frame_size - ADIN1110_FRAME_HEADER_LEN - ADIN1110_FEC_LEN; +- +- rxb = netdev_alloc_skb(port_priv->netdev, round_len); +- if (!rxb) +- return -ENOMEM; +- +- memset(priv->data, 0, round_len + ADIN1110_RD_HEADER_LEN); ++ memset(priv->data, 0, ADIN1110_RD_HEADER_LEN); + + priv->data[0] = ADIN1110_CD | FIELD_GET(GENMASK(12, 8), reg); + priv->data[1] = FIELD_GET(GENMASK(7, 0), reg); +@@ -342,21 +335,23 @@ static int adin1110_read_fifo(struct adin1110_port_priv *port_priv) + header_len++; + } + +- skb_put(rxb, frame_size_no_fcs + ADIN1110_FRAME_HEADER_LEN); ++ rxb = netdev_alloc_skb(port_priv->netdev, round_len + header_len); ++ if (!rxb) ++ return -ENOMEM; + +- t[0].tx_buf = &priv->data[0]; +- t[0].len = header_len; ++ skb_put(rxb, frame_size_no_fcs + header_len + ADIN1110_FRAME_HEADER_LEN); + +- t[1].rx_buf = &rxb->data[0]; +- t[1].len = round_len; ++ t.tx_buf = &priv->data[0]; ++ t.rx_buf = &rxb->data[0]; ++ t.len = header_len + round_len; + +- ret = spi_sync_transfer(priv->spidev, t, 2); ++ ret = spi_sync_transfer(priv->spidev, &t, 1); + if (ret) { + kfree_skb(rxb); + return ret; + } + +- skb_pull(rxb, ADIN1110_FRAME_HEADER_LEN); ++ skb_pull(rxb, header_len + ADIN1110_FRAME_HEADER_LEN); + rxb->protocol = eth_type_trans(rxb, port_priv->netdev); + + if ((port_priv->flags & IFF_ALLMULTI && rxb->pkt_type == PACKET_MULTICAST) || +diff --git a/drivers/net/ethernet/amd/atarilance.c b/drivers/net/ethernet/amd/atarilance.c +index 3222c48ce6ae4..ec704222925d8 100644 +--- a/drivers/net/ethernet/amd/atarilance.c ++++ b/drivers/net/ethernet/amd/atarilance.c +@@ -824,7 +824,7 @@ lance_start_xmit(struct sk_buff *skb, struct net_device *dev) + lp->memcpy_f( PKTBUF_ADDR(head), (void *)skb->data, skb->len ); + head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP; + dev->stats.tx_bytes += skb->len; +- dev_kfree_skb( skb ); ++ dev_consume_skb_irq(skb); + lp->cur_tx++; + while( lp->cur_tx >= TX_RING_SIZE && lp->dirty_tx >= TX_RING_SIZE ) { + lp->cur_tx -= TX_RING_SIZE; +diff --git a/drivers/net/ethernet/amd/lance.c b/drivers/net/ethernet/amd/lance.c +index fb8686214a327..8971665a4b2ac 100644 +--- a/drivers/net/ethernet/amd/lance.c ++++ b/drivers/net/ethernet/amd/lance.c +@@ -1001,7 +1001,7 @@ static netdev_tx_t lance_start_xmit(struct sk_buff *skb, + skb_copy_from_linear_data(skb, &lp->tx_bounce_buffs[entry], skb->len); + lp->tx_ring[entry].base = + ((u32)isa_virt_to_bus((lp->tx_bounce_buffs + entry)) & 0xffffff) | 0x83000000; +- dev_kfree_skb(skb); ++ dev_consume_skb_irq(skb); + } else { + lp->tx_skbuff[entry] = skb; + lp->tx_ring[entry].base = ((u32)isa_virt_to_bus(skb->data) & 0xffffff) | 0x83000000; +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +index 4064c3e3dd492..c731a04731f83 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +@@ -189,6 +189,7 @@ enum xgbe_sfp_cable { + XGBE_SFP_CABLE_UNKNOWN = 0, + XGBE_SFP_CABLE_ACTIVE, + XGBE_SFP_CABLE_PASSIVE, ++ XGBE_SFP_CABLE_FIBER, + }; + + enum xgbe_sfp_base { +@@ -236,10 +237,7 @@ enum xgbe_sfp_speed { + + #define XGBE_SFP_BASE_BR 12 + #define XGBE_SFP_BASE_BR_1GBE_MIN 0x0a +-#define XGBE_SFP_BASE_BR_1GBE_MAX 0x0d + #define XGBE_SFP_BASE_BR_10GBE_MIN 0x64 +-#define XGBE_SFP_BASE_BR_10GBE_MAX 0x68 +-#define XGBE_MOLEX_SFP_BASE_BR_10GBE_MAX 0x78 + + #define XGBE_SFP_BASE_CU_CABLE_LEN 18 + +@@ -826,29 +824,22 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata) + static bool xgbe_phy_sfp_bit_rate(struct xgbe_sfp_eeprom *sfp_eeprom, + enum xgbe_sfp_speed sfp_speed) + { +- u8 *sfp_base, min, max; ++ u8 *sfp_base, min; + + sfp_base = sfp_eeprom->base; + + switch (sfp_speed) { + case XGBE_SFP_SPEED_1000: + min = XGBE_SFP_BASE_BR_1GBE_MIN; +- max = XGBE_SFP_BASE_BR_1GBE_MAX; + break; + case XGBE_SFP_SPEED_10000: + min = XGBE_SFP_BASE_BR_10GBE_MIN; +- if (memcmp(&sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_NAME], +- XGBE_MOLEX_VENDOR, XGBE_SFP_BASE_VENDOR_NAME_LEN) == 0) +- max = XGBE_MOLEX_SFP_BASE_BR_10GBE_MAX; +- else +- max = XGBE_SFP_BASE_BR_10GBE_MAX; + break; + default: + return false; + } + +- return ((sfp_base[XGBE_SFP_BASE_BR] >= min) && +- (sfp_base[XGBE_SFP_BASE_BR] <= max)); ++ return sfp_base[XGBE_SFP_BASE_BR] >= min; + } + + static void xgbe_phy_free_phy_device(struct xgbe_prv_data *pdata) +@@ -1149,16 +1140,18 @@ static void xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata) + phy_data->sfp_tx_fault = xgbe_phy_check_sfp_tx_fault(phy_data); + phy_data->sfp_rx_los = xgbe_phy_check_sfp_rx_los(phy_data); + +- /* Assume ACTIVE cable unless told it is PASSIVE */ ++ /* Assume FIBER cable unless told otherwise */ + if (sfp_base[XGBE_SFP_BASE_CABLE] & XGBE_SFP_BASE_CABLE_PASSIVE) { + phy_data->sfp_cable = XGBE_SFP_CABLE_PASSIVE; + phy_data->sfp_cable_len = sfp_base[XGBE_SFP_BASE_CU_CABLE_LEN]; +- } else { ++ } else if (sfp_base[XGBE_SFP_BASE_CABLE] & XGBE_SFP_BASE_CABLE_ACTIVE) { + phy_data->sfp_cable = XGBE_SFP_CABLE_ACTIVE; ++ } else { ++ phy_data->sfp_cable = XGBE_SFP_CABLE_FIBER; + } + + /* Determine the type of SFP */ +- if (phy_data->sfp_cable == XGBE_SFP_CABLE_PASSIVE && ++ if (phy_data->sfp_cable != XGBE_SFP_CABLE_FIBER && + xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_10000)) + phy_data->sfp_base = XGBE_SFP_BASE_10000_CR; + else if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_SR) +diff --git a/drivers/net/ethernet/apple/bmac.c b/drivers/net/ethernet/apple/bmac.c +index 334de0d93c899..9e653e2925f78 100644 +--- a/drivers/net/ethernet/apple/bmac.c ++++ b/drivers/net/ethernet/apple/bmac.c +@@ -1510,7 +1510,7 @@ static void bmac_tx_timeout(struct timer_list *t) + i = bp->tx_empty; + ++dev->stats.tx_errors; + if (i != bp->tx_fill) { +- dev_kfree_skb(bp->tx_bufs[i]); ++ dev_kfree_skb_irq(bp->tx_bufs[i]); + bp->tx_bufs[i] = NULL; + if (++i >= N_TX_RING) i = 0; + bp->tx_empty = i; +diff --git a/drivers/net/ethernet/apple/mace.c b/drivers/net/ethernet/apple/mace.c +index d0a771b65e888..fd1b008b7208c 100644 +--- a/drivers/net/ethernet/apple/mace.c ++++ b/drivers/net/ethernet/apple/mace.c +@@ -846,7 +846,7 @@ static void mace_tx_timeout(struct timer_list *t) + if (mp->tx_bad_runt) { + mp->tx_bad_runt = 0; + } else if (i != mp->tx_fill) { +- dev_kfree_skb(mp->tx_bufs[i]); ++ dev_kfree_skb_irq(mp->tx_bufs[i]); + if (++i >= N_TX_RING) + i = 0; + mp->tx_empty = i; +diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c +index fec57f1982c86..dbe3101447804 100644 +--- a/drivers/net/ethernet/broadcom/bnx2.c ++++ b/drivers/net/ethernet/broadcom/bnx2.c +@@ -5415,8 +5415,9 @@ bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size) + + bp->rx_buf_use_size = rx_size; + /* hw alignment + build_skb() overhead*/ +- bp->rx_buf_size = SKB_DATA_ALIGN(bp->rx_buf_use_size + BNX2_RX_ALIGN) + +- NET_SKB_PAD + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); ++ bp->rx_buf_size = kmalloc_size_roundup( ++ SKB_DATA_ALIGN(bp->rx_buf_use_size + BNX2_RX_ALIGN) + ++ NET_SKB_PAD + SKB_DATA_ALIGN(sizeof(struct skb_shared_info))); + bp->rx_jumbo_thresh = rx_size - BNX2_RX_OFFSET; + bp->rx_ring_size = size; + bp->rx_max_ring = bnx2_find_max_ring(size, BNX2_MAX_RX_RINGS); +diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c +index 08184f20f5104..151ca9573be97 100644 +--- a/drivers/net/ethernet/dnet.c ++++ b/drivers/net/ethernet/dnet.c +@@ -550,11 +550,11 @@ static netdev_tx_t dnet_start_xmit(struct sk_buff *skb, struct net_device *dev) + + skb_tx_timestamp(skb); + ++ spin_unlock_irqrestore(&bp->lock, flags); ++ + /* free the buffer */ + dev_kfree_skb(skb); + +- spin_unlock_irqrestore(&bp->lock, flags); +- + return NETDEV_TX_OK; + } + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c +index 8671591cb7501..3a79ead5219ae 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc.c +@@ -1489,23 +1489,6 @@ static void enetc_xdp_drop(struct enetc_bdr *rx_ring, int rx_ring_first, + rx_ring->stats.xdp_drops++; + } + +-static void enetc_xdp_free(struct enetc_bdr *rx_ring, int rx_ring_first, +- int rx_ring_last) +-{ +- while (rx_ring_first != rx_ring_last) { +- struct enetc_rx_swbd *rx_swbd = &rx_ring->rx_swbd[rx_ring_first]; +- +- if (rx_swbd->page) { +- dma_unmap_page(rx_ring->dev, rx_swbd->dma, PAGE_SIZE, +- rx_swbd->dir); +- __free_page(rx_swbd->page); +- rx_swbd->page = NULL; +- } +- enetc_bdr_idx_inc(rx_ring, &rx_ring_first); +- } +- rx_ring->stats.xdp_redirect_failures++; +-} +- + static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring, + struct napi_struct *napi, int work_limit, + struct bpf_prog *prog) +@@ -1527,8 +1510,8 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring, + int orig_i, orig_cleaned_cnt; + struct xdp_buff xdp_buff; + struct sk_buff *skb; +- int tmp_orig_i, err; + u32 bd_status; ++ int err; + + rxbd = enetc_rxbd(rx_ring, i); + bd_status = le32_to_cpu(rxbd->r.lstatus); +@@ -1615,18 +1598,16 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring, + break; + } + +- tmp_orig_i = orig_i; +- +- while (orig_i != i) { +- enetc_flip_rx_buff(rx_ring, +- &rx_ring->rx_swbd[orig_i]); +- enetc_bdr_idx_inc(rx_ring, &orig_i); +- } +- + err = xdp_do_redirect(rx_ring->ndev, &xdp_buff, prog); + if (unlikely(err)) { +- enetc_xdp_free(rx_ring, tmp_orig_i, i); ++ enetc_xdp_drop(rx_ring, orig_i, i); ++ rx_ring->stats.xdp_redirect_failures++; + } else { ++ while (orig_i != i) { ++ enetc_flip_rx_buff(rx_ring, ++ &rx_ring->rx_swbd[orig_i]); ++ enetc_bdr_idx_inc(rx_ring, &orig_i); ++ } + xdp_redirect_frm_cnt++; + rx_ring->stats.xdp_redirect++; + } +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index 23e1a94b9ce45..f250b0df27fbb 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -1642,6 +1642,14 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + * bridging applications. + */ + skb = build_skb(page_address(page), PAGE_SIZE); ++ if (unlikely(!skb)) { ++ page_pool_recycle_direct(rxq->page_pool, page); ++ ndev->stats.rx_dropped++; ++ ++ netdev_err_once(ndev, "build_skb failed!\n"); ++ goto rx_processing_done; ++ } ++ + skb_reserve(skb, FEC_ENET_XDP_HEADROOM); + skb_put(skb, pkt_len - 4); + skb_mark_for_recycle(skb); +diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c +index 6416322d7c18b..e6e349f0c9457 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_main.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c +@@ -3693,6 +3693,24 @@ static int i40e_vsi_configure_tx(struct i40e_vsi *vsi) + return err; + } + ++/** ++ * i40e_calculate_vsi_rx_buf_len - Calculates buffer length ++ * ++ * @vsi: VSI to calculate rx_buf_len from ++ */ ++static u16 i40e_calculate_vsi_rx_buf_len(struct i40e_vsi *vsi) ++{ ++ if (!vsi->netdev || (vsi->back->flags & I40E_FLAG_LEGACY_RX)) ++ return I40E_RXBUFFER_2048; ++ ++#if (PAGE_SIZE < 8192) ++ if (!I40E_2K_TOO_SMALL_WITH_PADDING && vsi->netdev->mtu <= ETH_DATA_LEN) ++ return I40E_RXBUFFER_1536 - NET_IP_ALIGN; ++#endif ++ ++ return PAGE_SIZE < 8192 ? I40E_RXBUFFER_3072 : I40E_RXBUFFER_2048; ++} ++ + /** + * i40e_vsi_configure_rx - Configure the VSI for Rx + * @vsi: the VSI being configured +@@ -3704,20 +3722,14 @@ static int i40e_vsi_configure_rx(struct i40e_vsi *vsi) + int err = 0; + u16 i; + +- if (!vsi->netdev || (vsi->back->flags & I40E_FLAG_LEGACY_RX)) { +- vsi->max_frame = I40E_MAX_RXBUFFER; +- vsi->rx_buf_len = I40E_RXBUFFER_2048; ++ vsi->max_frame = I40E_MAX_RXBUFFER; ++ vsi->rx_buf_len = i40e_calculate_vsi_rx_buf_len(vsi); ++ + #if (PAGE_SIZE < 8192) +- } else if (!I40E_2K_TOO_SMALL_WITH_PADDING && +- (vsi->netdev->mtu <= ETH_DATA_LEN)) { ++ if (vsi->netdev && !I40E_2K_TOO_SMALL_WITH_PADDING && ++ vsi->netdev->mtu <= ETH_DATA_LEN) + vsi->max_frame = I40E_RXBUFFER_1536 - NET_IP_ALIGN; +- vsi->rx_buf_len = I40E_RXBUFFER_1536 - NET_IP_ALIGN; + #endif +- } else { +- vsi->max_frame = I40E_MAX_RXBUFFER; +- vsi->rx_buf_len = (PAGE_SIZE < 8192) ? I40E_RXBUFFER_3072 : +- I40E_RXBUFFER_2048; +- } + + /* set up individual rings */ + for (i = 0; i < vsi->num_queue_pairs && !err; i++) +@@ -13282,7 +13294,7 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi, struct bpf_prog *prog, + int i; + + /* Don't allow frames that span over multiple buffers */ +- if (frame_size > vsi->rx_buf_len) { ++ if (frame_size > i40e_calculate_vsi_rx_buf_len(vsi)) { + NL_SET_ERR_MSG_MOD(extack, "MTU too large to enable XDP"); + return -EINVAL; + } +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 0f668468d1414..53fec5bbe6e00 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -639,7 +639,7 @@ static u64 ice_ptp_extend_40b_ts(struct ice_pf *pf, u64 in_tstamp) + static bool ice_ptp_tx_tstamp(struct ice_ptp_tx *tx) + { + struct ice_ptp_port *ptp_port; +- bool ts_handled = true; ++ bool more_timestamps; + struct ice_pf *pf; + u8 idx; + +@@ -701,11 +701,10 @@ static bool ice_ptp_tx_tstamp(struct ice_ptp_tx *tx) + * poll for remaining timestamps. + */ + spin_lock(&tx->lock); +- if (!bitmap_empty(tx->in_use, tx->len)) +- ts_handled = false; ++ more_timestamps = tx->init && !bitmap_empty(tx->in_use, tx->len); + spin_unlock(&tx->lock); + +- return ts_handled; ++ return !more_timestamps; + } + + /** +@@ -776,6 +775,9 @@ ice_ptp_release_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx) + { + tx->init = 0; + ++ /* wait for potentially outstanding interrupt to complete */ ++ synchronize_irq(pf->msix_entries[pf->oicr_idx].vector); ++ + ice_ptp_flush_tx_tracker(pf, tx); + + kfree(tx->tstamps); +diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c +index f8e32833226c1..24a6ae19ad8ed 100644 +--- a/drivers/net/ethernet/intel/igb/igb_main.c ++++ b/drivers/net/ethernet/intel/igb/igb_main.c +@@ -1202,8 +1202,12 @@ static int igb_alloc_q_vector(struct igb_adapter *adapter, + if (!q_vector) { + q_vector = kzalloc(size, GFP_KERNEL); + } else if (size > ksize(q_vector)) { +- kfree_rcu(q_vector, rcu); +- q_vector = kzalloc(size, GFP_KERNEL); ++ struct igb_q_vector *new_q_vector; ++ ++ new_q_vector = kzalloc(size, GFP_KERNEL); ++ if (new_q_vector) ++ kfree_rcu(q_vector, rcu); ++ q_vector = new_q_vector; + } else { + memset(q_vector, 0, size); + } +@@ -7521,7 +7525,7 @@ static void igb_vf_reset_msg(struct igb_adapter *adapter, u32 vf) + { + struct e1000_hw *hw = &adapter->hw; + unsigned char *vf_mac = adapter->vf_data[vf].vf_mac_addresses; +- u32 reg, msgbuf[3]; ++ u32 reg, msgbuf[3] = {}; + u8 *addr = (u8 *)(&msgbuf[1]); + + /* process all the same items cleared in a function level reset */ +diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h +index 1e7e7071f64d2..df3e26c0cf01a 100644 +--- a/drivers/net/ethernet/intel/igc/igc.h ++++ b/drivers/net/ethernet/intel/igc/igc.h +@@ -94,6 +94,8 @@ struct igc_ring { + u8 queue_index; /* logical index of the ring*/ + u8 reg_idx; /* physical index of the ring */ + bool launchtime_enable; /* true if LaunchTime is enabled */ ++ ktime_t last_tx_cycle; /* end of the cycle with a launchtime transmission */ ++ ktime_t last_ff_cycle; /* Last cycle with an active first flag */ + + u32 start_time; + u32 end_time; +@@ -182,6 +184,7 @@ struct igc_adapter { + + ktime_t base_time; + ktime_t cycle_time; ++ bool qbv_enable; + + /* OS defined structs */ + struct pci_dev *pdev; +diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h +index 4f9d7f013a958..4ad35fbdc02e8 100644 +--- a/drivers/net/ethernet/intel/igc/igc_defines.h ++++ b/drivers/net/ethernet/intel/igc/igc_defines.h +@@ -321,6 +321,8 @@ + #define IGC_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ + #define IGC_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ + ++#define IGC_ADVTXD_TSN_CNTX_FIRST 0x00000080 ++ + /* Transmit Control */ + #define IGC_TCTL_EN 0x00000002 /* enable Tx */ + #define IGC_TCTL_PSP 0x00000008 /* pad short packets */ +diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c +index 34889be63e788..34db1c006b20a 100644 +--- a/drivers/net/ethernet/intel/igc/igc_main.c ++++ b/drivers/net/ethernet/intel/igc/igc_main.c +@@ -1000,25 +1000,118 @@ static int igc_write_mc_addr_list(struct net_device *netdev) + return netdev_mc_count(netdev); + } + +-static __le32 igc_tx_launchtime(struct igc_adapter *adapter, ktime_t txtime) ++static __le32 igc_tx_launchtime(struct igc_ring *ring, ktime_t txtime, ++ bool *first_flag, bool *insert_empty) + { ++ struct igc_adapter *adapter = netdev_priv(ring->netdev); + ktime_t cycle_time = adapter->cycle_time; + ktime_t base_time = adapter->base_time; ++ ktime_t now = ktime_get_clocktai(); ++ ktime_t baset_est, end_of_cycle; + u32 launchtime; ++ s64 n; + +- /* FIXME: when using ETF together with taprio, we may have a +- * case where 'delta' is larger than the cycle_time, this may +- * cause problems if we don't read the current value of +- * IGC_BASET, as the value writen into the launchtime +- * descriptor field may be misinterpreted. ++ n = div64_s64(ktime_sub_ns(now, base_time), cycle_time); ++ ++ baset_est = ktime_add_ns(base_time, cycle_time * (n)); ++ end_of_cycle = ktime_add_ns(baset_est, cycle_time); ++ ++ if (ktime_compare(txtime, end_of_cycle) >= 0) { ++ if (baset_est != ring->last_ff_cycle) { ++ *first_flag = true; ++ ring->last_ff_cycle = baset_est; ++ ++ if (ktime_compare(txtime, ring->last_tx_cycle) > 0) ++ *insert_empty = true; ++ } ++ } ++ ++ /* Introducing a window at end of cycle on which packets ++ * potentially not honor launchtime. Window of 5us chosen ++ * considering software update the tail pointer and packets ++ * are dma'ed to packet buffer. + */ +- div_s64_rem(ktime_sub_ns(txtime, base_time), cycle_time, &launchtime); ++ if ((ktime_sub_ns(end_of_cycle, now) < 5 * NSEC_PER_USEC)) ++ netdev_warn(ring->netdev, "Packet with txtime=%llu may not be honoured\n", ++ txtime); ++ ++ ring->last_tx_cycle = end_of_cycle; ++ ++ launchtime = ktime_sub_ns(txtime, baset_est); ++ if (launchtime > 0) ++ div_s64_rem(launchtime, cycle_time, &launchtime); ++ else ++ launchtime = 0; + + return cpu_to_le32(launchtime); + } + ++static int igc_init_empty_frame(struct igc_ring *ring, ++ struct igc_tx_buffer *buffer, ++ struct sk_buff *skb) ++{ ++ unsigned int size; ++ dma_addr_t dma; ++ ++ size = skb_headlen(skb); ++ ++ dma = dma_map_single(ring->dev, skb->data, size, DMA_TO_DEVICE); ++ if (dma_mapping_error(ring->dev, dma)) { ++ netdev_err_once(ring->netdev, "Failed to map DMA for TX\n"); ++ return -ENOMEM; ++ } ++ ++ buffer->skb = skb; ++ buffer->protocol = 0; ++ buffer->bytecount = skb->len; ++ buffer->gso_segs = 1; ++ buffer->time_stamp = jiffies; ++ dma_unmap_len_set(buffer, len, skb->len); ++ dma_unmap_addr_set(buffer, dma, dma); ++ ++ return 0; ++} ++ ++static int igc_init_tx_empty_descriptor(struct igc_ring *ring, ++ struct sk_buff *skb, ++ struct igc_tx_buffer *first) ++{ ++ union igc_adv_tx_desc *desc; ++ u32 cmd_type, olinfo_status; ++ int err; ++ ++ if (!igc_desc_unused(ring)) ++ return -EBUSY; ++ ++ err = igc_init_empty_frame(ring, first, skb); ++ if (err) ++ return err; ++ ++ cmd_type = IGC_ADVTXD_DTYP_DATA | IGC_ADVTXD_DCMD_DEXT | ++ IGC_ADVTXD_DCMD_IFCS | IGC_TXD_DCMD | ++ first->bytecount; ++ olinfo_status = first->bytecount << IGC_ADVTXD_PAYLEN_SHIFT; ++ ++ desc = IGC_TX_DESC(ring, ring->next_to_use); ++ desc->read.cmd_type_len = cpu_to_le32(cmd_type); ++ desc->read.olinfo_status = cpu_to_le32(olinfo_status); ++ desc->read.buffer_addr = cpu_to_le64(dma_unmap_addr(first, dma)); ++ ++ netdev_tx_sent_queue(txring_txq(ring), skb->len); ++ ++ first->next_to_watch = desc; ++ ++ ring->next_to_use++; ++ if (ring->next_to_use == ring->count) ++ ring->next_to_use = 0; ++ ++ return 0; ++} ++ ++#define IGC_EMPTY_FRAME_SIZE 60 ++ + static void igc_tx_ctxtdesc(struct igc_ring *tx_ring, +- struct igc_tx_buffer *first, ++ __le32 launch_time, bool first_flag, + u32 vlan_macip_lens, u32 type_tucmd, + u32 mss_l4len_idx) + { +@@ -1037,26 +1130,17 @@ static void igc_tx_ctxtdesc(struct igc_ring *tx_ring, + if (test_bit(IGC_RING_FLAG_TX_CTX_IDX, &tx_ring->flags)) + mss_l4len_idx |= tx_ring->reg_idx << 4; + ++ if (first_flag) ++ mss_l4len_idx |= IGC_ADVTXD_TSN_CNTX_FIRST; ++ + context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens); + context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd); + context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx); +- +- /* We assume there is always a valid Tx time available. Invalid times +- * should have been handled by the upper layers. +- */ +- if (tx_ring->launchtime_enable) { +- struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); +- ktime_t txtime = first->skb->tstamp; +- +- skb_txtime_consumed(first->skb); +- context_desc->launch_time = igc_tx_launchtime(adapter, +- txtime); +- } else { +- context_desc->launch_time = 0; +- } ++ context_desc->launch_time = launch_time; + } + +-static void igc_tx_csum(struct igc_ring *tx_ring, struct igc_tx_buffer *first) ++static void igc_tx_csum(struct igc_ring *tx_ring, struct igc_tx_buffer *first, ++ __le32 launch_time, bool first_flag) + { + struct sk_buff *skb = first->skb; + u32 vlan_macip_lens = 0; +@@ -1096,7 +1180,8 @@ no_csum: + vlan_macip_lens |= skb_network_offset(skb) << IGC_ADVTXD_MACLEN_SHIFT; + vlan_macip_lens |= first->tx_flags & IGC_TX_FLAGS_VLAN_MASK; + +- igc_tx_ctxtdesc(tx_ring, first, vlan_macip_lens, type_tucmd, 0); ++ igc_tx_ctxtdesc(tx_ring, launch_time, first_flag, ++ vlan_macip_lens, type_tucmd, 0); + } + + static int __igc_maybe_stop_tx(struct igc_ring *tx_ring, const u16 size) +@@ -1320,6 +1405,7 @@ dma_error: + + static int igc_tso(struct igc_ring *tx_ring, + struct igc_tx_buffer *first, ++ __le32 launch_time, bool first_flag, + u8 *hdr_len) + { + u32 vlan_macip_lens, type_tucmd, mss_l4len_idx; +@@ -1406,8 +1492,8 @@ static int igc_tso(struct igc_ring *tx_ring, + vlan_macip_lens |= (ip.hdr - skb->data) << IGC_ADVTXD_MACLEN_SHIFT; + vlan_macip_lens |= first->tx_flags & IGC_TX_FLAGS_VLAN_MASK; + +- igc_tx_ctxtdesc(tx_ring, first, vlan_macip_lens, +- type_tucmd, mss_l4len_idx); ++ igc_tx_ctxtdesc(tx_ring, launch_time, first_flag, ++ vlan_macip_lens, type_tucmd, mss_l4len_idx); + + return 1; + } +@@ -1415,11 +1501,14 @@ static int igc_tso(struct igc_ring *tx_ring, + static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb, + struct igc_ring *tx_ring) + { ++ bool first_flag = false, insert_empty = false; + u16 count = TXD_USE_COUNT(skb_headlen(skb)); + __be16 protocol = vlan_get_protocol(skb); + struct igc_tx_buffer *first; ++ __le32 launch_time = 0; + u32 tx_flags = 0; + unsigned short f; ++ ktime_t txtime; + u8 hdr_len = 0; + int tso = 0; + +@@ -1433,11 +1522,40 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb, + count += TXD_USE_COUNT(skb_frag_size( + &skb_shinfo(skb)->frags[f])); + +- if (igc_maybe_stop_tx(tx_ring, count + 3)) { ++ if (igc_maybe_stop_tx(tx_ring, count + 5)) { + /* this is a hard error */ + return NETDEV_TX_BUSY; + } + ++ if (!tx_ring->launchtime_enable) ++ goto done; ++ ++ txtime = skb->tstamp; ++ skb->tstamp = ktime_set(0, 0); ++ launch_time = igc_tx_launchtime(tx_ring, txtime, &first_flag, &insert_empty); ++ ++ if (insert_empty) { ++ struct igc_tx_buffer *empty_info; ++ struct sk_buff *empty; ++ void *data; ++ ++ empty_info = &tx_ring->tx_buffer_info[tx_ring->next_to_use]; ++ empty = alloc_skb(IGC_EMPTY_FRAME_SIZE, GFP_ATOMIC); ++ if (!empty) ++ goto done; ++ ++ data = skb_put(empty, IGC_EMPTY_FRAME_SIZE); ++ memset(data, 0, IGC_EMPTY_FRAME_SIZE); ++ ++ igc_tx_ctxtdesc(tx_ring, 0, false, 0, 0, 0); ++ ++ if (igc_init_tx_empty_descriptor(tx_ring, ++ empty, ++ empty_info) < 0) ++ dev_kfree_skb_any(empty); ++ } ++ ++done: + /* record the location of the first descriptor for this packet */ + first = &tx_ring->tx_buffer_info[tx_ring->next_to_use]; + first->type = IGC_TX_BUFFER_TYPE_SKB; +@@ -1474,11 +1592,11 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb, + first->tx_flags = tx_flags; + first->protocol = protocol; + +- tso = igc_tso(tx_ring, first, &hdr_len); ++ tso = igc_tso(tx_ring, first, launch_time, first_flag, &hdr_len); + if (tso < 0) + goto out_drop; + else if (!tso) +- igc_tx_csum(tx_ring, first); ++ igc_tx_csum(tx_ring, first, launch_time, first_flag); + + igc_tx_map(tx_ring, first, hdr_len); + +@@ -5918,10 +6036,16 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, + bool queue_configured[IGC_MAX_TX_QUEUES] = { }; + u32 start_time = 0, end_time = 0; + size_t n; ++ int i; ++ ++ adapter->qbv_enable = qopt->enable; + + if (!qopt->enable) + return igc_tsn_clear_schedule(adapter); + ++ if (qopt->base_time < 0) ++ return -ERANGE; ++ + if (adapter->base_time) + return -EALREADY; + +@@ -5933,10 +6057,24 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, + + for (n = 0; n < qopt->num_entries; n++) { + struct tc_taprio_sched_entry *e = &qopt->entries[n]; +- int i; + + end_time += e->interval; + ++ /* If any of the conditions below are true, we need to manually ++ * control the end time of the cycle. ++ * 1. Qbv users can specify a cycle time that is not equal ++ * to the total GCL intervals. Hence, recalculation is ++ * necessary here to exclude the time interval that ++ * exceeds the cycle time. ++ * 2. According to IEEE Std. 802.1Q-2018 section 8.6.9.2, ++ * once the end of the list is reached, it will switch ++ * to the END_OF_CYCLE state and leave the gates in the ++ * same state until the next cycle is started. ++ */ ++ if (end_time > adapter->cycle_time || ++ n + 1 == qopt->num_entries) ++ end_time = adapter->cycle_time; ++ + for (i = 0; i < adapter->num_tx_queues; i++) { + struct igc_ring *ring = adapter->tx_ring[i]; + +@@ -5957,6 +6095,18 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, + start_time += e->interval; + } + ++ /* Check whether a queue gets configured. ++ * If not, set the start and end time to be end time. ++ */ ++ for (i = 0; i < adapter->num_tx_queues; i++) { ++ if (!queue_configured[i]) { ++ struct igc_ring *ring = adapter->tx_ring[i]; ++ ++ ring->start_time = end_time; ++ ring->end_time = end_time; ++ } ++ } ++ + return 0; + } + +diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c +index 0fce22de2ab85..356c7455c5cee 100644 +--- a/drivers/net/ethernet/intel/igc/igc_tsn.c ++++ b/drivers/net/ethernet/intel/igc/igc_tsn.c +@@ -36,7 +36,7 @@ static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter) + { + unsigned int new_flags = adapter->flags & ~IGC_FLAG_TSN_ANY_ENABLED; + +- if (adapter->base_time) ++ if (adapter->qbv_enable) + new_flags |= IGC_FLAG_TSN_QBV_ENABLED; + + if (is_any_launchtime(adapter)) +@@ -110,15 +110,8 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter) + wr32(IGC_STQT(i), ring->start_time); + wr32(IGC_ENDQT(i), ring->end_time); + +- if (adapter->base_time) { +- /* If we have a base_time we are in "taprio" +- * mode and we need to be strict about the +- * cycles: only transmit a packet if it can be +- * completed during that cycle. +- */ +- txqctl |= IGC_TXQCTL_STRICT_CYCLE | +- IGC_TXQCTL_STRICT_END; +- } ++ txqctl |= IGC_TXQCTL_STRICT_CYCLE | ++ IGC_TXQCTL_STRICT_END; + + if (ring->launchtime_enable) + txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT; +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mcs.c b/drivers/net/ethernet/marvell/octeontx2/af/mcs.c +index c0bedf402da93..f68a6a0e3aa41 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/mcs.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/mcs.c +@@ -1184,10 +1184,13 @@ static int mcs_register_interrupts(struct mcs *mcs) + mcs->tx_sa_active = alloc_mem(mcs, mcs->hw->sc_entries); + if (!mcs->tx_sa_active) { + ret = -ENOMEM; +- goto exit; ++ goto free_irq; + } + + return ret; ++ ++free_irq: ++ free_irq(pci_irq_vector(mcs->pdev, MCS_INT_VEC_IP), mcs); + exit: + pci_free_irq_vectors(mcs->pdev); + mcs->num_vec = 0; +@@ -1589,6 +1592,7 @@ static void mcs_remove(struct pci_dev *pdev) + + /* Set MCS to external bypass */ + mcs_set_external_bypass(mcs, true); ++ free_irq(pci_irq_vector(pdev, MCS_INT_VEC_IP), mcs); + pci_free_irq_vectors(pdev); + pci_release_regions(pdev); + pci_disable_device(pdev); +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 1d36619c5ec91..9aa1892a609c7 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3229,6 +3229,30 @@ static void mtk_dim_tx(struct work_struct *work) + dim->state = DIM_START_MEASURE; + } + ++static void mtk_set_mcr_max_rx(struct mtk_mac *mac, u32 val) ++{ ++ struct mtk_eth *eth = mac->hw; ++ u32 mcr_cur, mcr_new; ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) ++ return; ++ ++ mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); ++ mcr_new = mcr_cur & ~MAC_MCR_MAX_RX_MASK; ++ ++ if (val <= 1518) ++ mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_1518); ++ else if (val <= 1536) ++ mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_1536); ++ else if (val <= 1552) ++ mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_1552); ++ else ++ mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_2048); ++ ++ if (mcr_new != mcr_cur) ++ mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id)); ++} ++ + static int mtk_hw_init(struct mtk_eth *eth) + { + u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | +@@ -3268,16 +3292,17 @@ static int mtk_hw_init(struct mtk_eth *eth) + return 0; + } + +- val = RSTCTRL_FE | RSTCTRL_PPE; + if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0); +- +- val |= RSTCTRL_ETH; +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) +- val |= RSTCTRL_PPE1; ++ val = RSTCTRL_PPE0_V2; ++ } else { ++ val = RSTCTRL_PPE0; + } + +- ethsys_reset(eth, val); ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) ++ val |= RSTCTRL_PPE1; ++ ++ ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | val); + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, +@@ -3303,8 +3328,16 @@ static int mtk_hw_init(struct mtk_eth *eth) + * up with the more appropriate value when mtk_mac_config call is being + * invoked. + */ +- for (i = 0; i < MTK_MAC_COUNT; i++) ++ for (i = 0; i < MTK_MAC_COUNT; i++) { ++ struct net_device *dev = eth->netdev[i]; ++ + mtk_w32(eth, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(i)); ++ if (dev) { ++ struct mtk_mac *mac = netdev_priv(dev); ++ ++ mtk_set_mcr_max_rx(mac, dev->mtu + MTK_RX_ETH_HLEN); ++ } ++ } + + /* Indicates CDM to parse the MTK special tag from CPU + * which also is working out for untag packets. +@@ -3331,9 +3364,12 @@ static int mtk_hw_init(struct mtk_eth *eth) + mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { +- /* PSE should not drop port8 and port9 packets */ ++ /* PSE should not drop port8 and port9 packets from WDMA Tx */ + mtk_w32(eth, 0x00000300, PSE_DROP_CFG); + ++ /* PSE should drop packets to port 8/9 on WDMA Rx ring full */ ++ mtk_w32(eth, 0x00000300, PSE_PPE0_DROP); ++ + /* PSE Free Queue Flow Control */ + mtk_w32(eth, 0x01fa01f4, PSE_FQFC_CFG2); + +@@ -3420,7 +3456,6 @@ static int mtk_change_mtu(struct net_device *dev, int new_mtu) + int length = new_mtu + MTK_RX_ETH_HLEN; + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; +- u32 mcr_cur, mcr_new; + + if (rcu_access_pointer(eth->prog) && + length > MTK_PP_MAX_BUF_SIZE) { +@@ -3428,23 +3463,7 @@ static int mtk_change_mtu(struct net_device *dev, int new_mtu) + return -EINVAL; + } + +- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) { +- mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); +- mcr_new = mcr_cur & ~MAC_MCR_MAX_RX_MASK; +- +- if (length <= 1518) +- mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_1518); +- else if (length <= 1536) +- mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_1536); +- else if (length <= 1552) +- mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_1552); +- else +- mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_2048); +- +- if (mcr_new != mcr_cur) +- mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id)); +- } +- ++ mtk_set_mcr_max_rx(mac, length); + dev->mtu = new_mtu; + + return 0; +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +index b52f3b0177efb..306fdc2c608a4 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -120,6 +120,7 @@ + #define PSE_FQFC_CFG1 0x100 + #define PSE_FQFC_CFG2 0x104 + #define PSE_DROP_CFG 0x108 ++#define PSE_PPE0_DROP 0x110 + + /* PSE Input Queue Reservation Register*/ + #define PSE_IQ_REV(x) (0x140 + (((x) - 1) << 2)) +@@ -447,18 +448,14 @@ + /* ethernet reset control register */ + #define ETHSYS_RSTCTRL 0x34 + #define RSTCTRL_FE BIT(6) +-#define RSTCTRL_PPE BIT(31) +-#define RSTCTRL_PPE1 BIT(30) ++#define RSTCTRL_PPE0 BIT(31) ++#define RSTCTRL_PPE0_V2 BIT(30) ++#define RSTCTRL_PPE1 BIT(31) + #define RSTCTRL_ETH BIT(23) + + /* ethernet reset check idle register */ + #define ETHSYS_FE_RST_CHK_IDLE_EN 0x28 + +-/* ethernet reset control register */ +-#define ETHSYS_RSTCTRL 0x34 +-#define RSTCTRL_FE BIT(6) +-#define RSTCTRL_PPE BIT(31) +- + /* ethernet dma channel agent map */ + #define ETHSYS_DMA_AG_MAP 0x408 + #define ETHSYS_DMA_AG_MAP_PDMA BIT(0) +diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +index 9063e2e22cd5c..9a9341a348c00 100644 +--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c ++++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +@@ -3913,6 +3913,7 @@ abort_with_slices: + myri10ge_free_slices(mgp); + + abort_with_firmware: ++ kfree(mgp->msix_vectors); + myri10ge_dummy_rdma(mgp, 0); + + abort_with_ioremap: +diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c +index 1d3c4474b7cb4..700c05fb05b97 100644 +--- a/drivers/net/ethernet/neterion/s2io.c ++++ b/drivers/net/ethernet/neterion/s2io.c +@@ -2386,7 +2386,7 @@ static void free_tx_buffers(struct s2io_nic *nic) + skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j); + if (skb) { + swstats->mem_freed += skb->truesize; +- dev_kfree_skb(skb); ++ dev_kfree_skb_irq(skb); + cnt++; + } + } +diff --git a/drivers/net/ethernet/qlogic/qed/qed_debug.c b/drivers/net/ethernet/qlogic/qed/qed_debug.c +index 5250d1d1e49ca..86ecb080b1536 100644 +--- a/drivers/net/ethernet/qlogic/qed/qed_debug.c ++++ b/drivers/net/ethernet/qlogic/qed/qed_debug.c +@@ -1972,9 +1972,10 @@ static u32 qed_grc_dump_addr_range(struct qed_hwfn *p_hwfn, + u8 split_id) + { + struct dbg_tools_data *dev_data = &p_hwfn->dbg_info; +- u8 port_id = 0, pf_id = 0, vf_id = 0, fid = 0; ++ u8 port_id = 0, pf_id = 0, vf_id = 0; + bool read_using_dmae = false; + u32 thresh; ++ u16 fid; + + if (!dump) + return len; +diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +index 9282321c2e7fb..f9dd50152b1e3 100644 +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +@@ -221,6 +221,8 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs) + return 0; + + qlcnic_destroy_async_wq: ++ while (i--) ++ kfree(sriov->vf_info[i].vp); + destroy_workqueue(bc->bc_async_wq); + + qlcnic_destroy_trans_wq: +diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c +index eecd52ed1ed21..f4d434c379e7c 100644 +--- a/drivers/net/ethernet/rdc/r6040.c ++++ b/drivers/net/ethernet/rdc/r6040.c +@@ -1159,10 +1159,12 @@ static int r6040_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + err = register_netdev(dev); + if (err) { + dev_err(&pdev->dev, "Failed to register net device\n"); +- goto err_out_mdio_unregister; ++ goto err_out_phy_disconnect; + } + return 0; + ++err_out_phy_disconnect: ++ phy_disconnect(dev->phydev); + err_out_mdio_unregister: + mdiobus_unregister(lp->mii_bus); + err_out_mdio: +@@ -1186,6 +1188,7 @@ static void r6040_remove_one(struct pci_dev *pdev) + struct r6040_private *lp = netdev_priv(dev); + + unregister_netdev(dev); ++ phy_disconnect(dev->phydev); + mdiobus_unregister(lp->mii_bus); + mdiobus_free(lp->mii_bus); + netif_napi_del(&lp->napi); +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c +index 764832f4dae1a..8b50f03056b7b 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c +@@ -47,7 +47,8 @@ static void config_sub_second_increment(void __iomem *ioaddr, + if (!(value & PTP_TCR_TSCTRLSSR)) + data = (data * 1000) / 465; + +- data &= PTP_SSIR_SSINC_MASK; ++ if (data > PTP_SSIR_SSINC_MAX) ++ data = PTP_SSIR_SSINC_MAX; + + reg_value = data; + if (gmac4) +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 23ec0a9e396c6..feb209d4b991e 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -7097,7 +7097,8 @@ int stmmac_dvr_probe(struct device *device, + priv->wq = create_singlethread_workqueue("stmmac_wq"); + if (!priv->wq) { + dev_err(priv->device, "failed to create workqueue\n"); +- return -ENOMEM; ++ ret = -ENOMEM; ++ goto error_wq_init; + } + + INIT_WORK(&priv->service_task, stmmac_service_task); +@@ -7325,6 +7326,7 @@ error_mdio_register: + stmmac_napi_del(ndev); + error_hw_init: + destroy_workqueue(priv->wq); ++error_wq_init: + bitmap_free(priv->af_xdp_zc_qps); + + return ret; +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h +index 53172a4398101..bf619295d079f 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h +@@ -64,7 +64,7 @@ + #define PTP_TCR_TSENMACADDR BIT(18) + + /* SSIR defines */ +-#define PTP_SSIR_SSINC_MASK 0xff ++#define PTP_SSIR_SSINC_MAX 0xff + #define GMAC4_PTP_SSIR_SSINC_SHIFT 16 + + /* Auxiliary Control defines */ +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +index 49af7e78b7f59..687f43cd466c6 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +@@ -1654,12 +1654,16 @@ static int stmmac_test_arpoffload(struct stmmac_priv *priv) + } + + ret = stmmac_set_arp_offload(priv, priv->hw, true, ip_addr); +- if (ret) ++ if (ret) { ++ kfree_skb(skb); + goto cleanup; ++ } + + ret = dev_set_promiscuity(priv->dev, 1); +- if (ret) ++ if (ret) { ++ kfree_skb(skb); + goto cleanup; ++ } + + ret = dev_direct_xmit(skb, 0); + if (ret) +diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c +index b3b0ba842541d..4ff1cfdb9730c 100644 +--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c ++++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c +@@ -564,13 +564,13 @@ static int am65_cpsw_nuss_ndo_slave_open(struct net_device *ndev) + ret = netif_set_real_num_tx_queues(ndev, common->tx_ch_num); + if (ret) { + dev_err(common->dev, "cannot set real number of tx queues\n"); +- return ret; ++ goto runtime_put; + } + + ret = netif_set_real_num_rx_queues(ndev, AM65_CPSW_MAX_RX_QUEUES); + if (ret) { + dev_err(common->dev, "cannot set real number of rx queues\n"); +- return ret; ++ goto runtime_put; + } + + for (i = 0; i < common->tx_ch_num; i++) +@@ -578,7 +578,7 @@ static int am65_cpsw_nuss_ndo_slave_open(struct net_device *ndev) + + ret = am65_cpsw_nuss_common_open(common); + if (ret) +- return ret; ++ goto runtime_put; + + common->usage_count++; + +@@ -606,6 +606,10 @@ static int am65_cpsw_nuss_ndo_slave_open(struct net_device *ndev) + error_cleanup: + am65_cpsw_nuss_ndo_slave_stop(ndev); + return ret; ++ ++runtime_put: ++ pm_runtime_put(common->dev); ++ return ret; + } + + static void am65_cpsw_nuss_rx_cleanup(void *data, dma_addr_t desc_dma) +diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c +index aba70bef48945..9eb9eaff4dc90 100644 +--- a/drivers/net/ethernet/ti/netcp_core.c ++++ b/drivers/net/ethernet/ti/netcp_core.c +@@ -1261,7 +1261,7 @@ out: + } + + /* Submit the packet */ +-static int netcp_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev) ++static netdev_tx_t netcp_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev) + { + struct netcp_intf *netcp = netdev_priv(ndev); + struct netcp_stats *tx_stats = &netcp->stats; +diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c +index a3967f8de417d..ad2c30d9a4824 100644 +--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c ++++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c +@@ -536,7 +536,7 @@ static void xemaclite_tx_timeout(struct net_device *dev, unsigned int txqueue) + xemaclite_enable_interrupts(lp); + + if (lp->deferred_skb) { +- dev_kfree_skb(lp->deferred_skb); ++ dev_kfree_skb_irq(lp->deferred_skb); + lp->deferred_skb = NULL; + dev->stats.tx_errors++; + } +diff --git a/drivers/net/fddi/defxx.c b/drivers/net/fddi/defxx.c +index b584ffe38ad68..1fef8a9b1a0fd 100644 +--- a/drivers/net/fddi/defxx.c ++++ b/drivers/net/fddi/defxx.c +@@ -3831,10 +3831,24 @@ static int dfx_init(void) + int status; + + status = pci_register_driver(&dfx_pci_driver); +- if (!status) +- status = eisa_driver_register(&dfx_eisa_driver); +- if (!status) +- status = tc_register_driver(&dfx_tc_driver); ++ if (status) ++ goto err_pci_register; ++ ++ status = eisa_driver_register(&dfx_eisa_driver); ++ if (status) ++ goto err_eisa_register; ++ ++ status = tc_register_driver(&dfx_tc_driver); ++ if (status) ++ goto err_tc_register; ++ ++ return 0; ++ ++err_tc_register: ++ eisa_driver_unregister(&dfx_eisa_driver); ++err_eisa_register: ++ pci_unregister_driver(&dfx_pci_driver); ++err_pci_register: + return status; + } + +diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c +index 791b4a53d69fd..bd3b0c2655a28 100644 +--- a/drivers/net/hamradio/baycom_epp.c ++++ b/drivers/net/hamradio/baycom_epp.c +@@ -758,7 +758,7 @@ static void epp_bh(struct work_struct *work) + * ===================== network driver interface ========================= + */ + +-static int baycom_send_packet(struct sk_buff *skb, struct net_device *dev) ++static netdev_tx_t baycom_send_packet(struct sk_buff *skb, struct net_device *dev) + { + struct baycom_state *bc = netdev_priv(dev); + +diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c +index f90830d3dfa69..a9184a78650b0 100644 +--- a/drivers/net/hamradio/scc.c ++++ b/drivers/net/hamradio/scc.c +@@ -302,12 +302,12 @@ static inline void scc_discard_buffers(struct scc_channel *scc) + spin_lock_irqsave(&scc->lock, flags); + if (scc->tx_buff != NULL) + { +- dev_kfree_skb(scc->tx_buff); ++ dev_kfree_skb_irq(scc->tx_buff); + scc->tx_buff = NULL; + } + + while (!skb_queue_empty(&scc->tx_queue)) +- dev_kfree_skb(skb_dequeue(&scc->tx_queue)); ++ dev_kfree_skb_irq(skb_dequeue(&scc->tx_queue)); + + spin_unlock_irqrestore(&scc->lock, flags); + } +@@ -1668,7 +1668,7 @@ static netdev_tx_t scc_net_tx(struct sk_buff *skb, struct net_device *dev) + if (skb_queue_len(&scc->tx_queue) > scc->dev->tx_queue_len) { + struct sk_buff *skb_del; + skb_del = skb_dequeue(&scc->tx_queue); +- dev_kfree_skb(skb_del); ++ dev_kfree_skb_irq(skb_del); + } + skb_queue_tail(&scc->tx_queue, skb); + netif_trans_update(dev); +diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c +index 2fbac51b9b19e..038a787943927 100644 +--- a/drivers/net/macsec.c ++++ b/drivers/net/macsec.c +@@ -2593,7 +2593,7 @@ static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info) + const struct macsec_ops *ops; + struct macsec_context ctx; + struct macsec_dev *macsec; +- int ret; ++ int ret = 0; + + if (!attrs[MACSEC_ATTR_IFINDEX]) + return -EINVAL; +@@ -2606,28 +2606,36 @@ static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info) + macsec_genl_offload_policy, NULL)) + return -EINVAL; + ++ rtnl_lock(); ++ + dev = get_dev_from_nl(genl_info_net(info), attrs); +- if (IS_ERR(dev)) +- return PTR_ERR(dev); ++ if (IS_ERR(dev)) { ++ ret = PTR_ERR(dev); ++ goto out; ++ } + macsec = macsec_priv(dev); + +- if (!tb_offload[MACSEC_OFFLOAD_ATTR_TYPE]) +- return -EINVAL; ++ if (!tb_offload[MACSEC_OFFLOAD_ATTR_TYPE]) { ++ ret = -EINVAL; ++ goto out; ++ } + + offload = nla_get_u8(tb_offload[MACSEC_OFFLOAD_ATTR_TYPE]); + if (macsec->offload == offload) +- return 0; ++ goto out; + + /* Check if the offloading mode is supported by the underlying layers */ + if (offload != MACSEC_OFFLOAD_OFF && +- !macsec_check_offload(offload, macsec)) +- return -EOPNOTSUPP; ++ !macsec_check_offload(offload, macsec)) { ++ ret = -EOPNOTSUPP; ++ goto out; ++ } + + /* Check if the net device is busy. */ +- if (netif_running(dev)) +- return -EBUSY; +- +- rtnl_lock(); ++ if (netif_running(dev)) { ++ ret = -EBUSY; ++ goto out; ++ } + + prev_offload = macsec->offload; + macsec->offload = offload; +@@ -2662,7 +2670,7 @@ static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info) + + rollback: + macsec->offload = prev_offload; +- ++out: + rtnl_unlock(); + return ret; + } +diff --git a/drivers/net/mctp/mctp-serial.c b/drivers/net/mctp/mctp-serial.c +index 7cd103fd34ef7..9f9eaf896047c 100644 +--- a/drivers/net/mctp/mctp-serial.c ++++ b/drivers/net/mctp/mctp-serial.c +@@ -35,6 +35,8 @@ + #define BYTE_FRAME 0x7e + #define BYTE_ESC 0x7d + ++#define FCS_INIT 0xffff ++ + static DEFINE_IDA(mctp_serial_ida); + + enum mctp_serial_state { +@@ -123,7 +125,7 @@ static void mctp_serial_tx_work(struct work_struct *work) + buf[2] = dev->txlen; + + if (!dev->txpos) +- dev->txfcs = crc_ccitt(0, buf + 1, 2); ++ dev->txfcs = crc_ccitt(FCS_INIT, buf + 1, 2); + + txlen = write_chunk(dev, buf + dev->txpos, 3 - dev->txpos); + if (txlen <= 0) { +@@ -303,7 +305,7 @@ static void mctp_serial_push_header(struct mctp_serial *dev, unsigned char c) + case 1: + if (c == MCTP_SERIAL_VERSION) { + dev->rxpos++; +- dev->rxfcs = crc_ccitt_byte(0, c); ++ dev->rxfcs = crc_ccitt_byte(FCS_INIT, c); + } else { + dev->rxstate = STATE_ERR; + } +diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c +index a4abea921046b..85dbe7f73e319 100644 +--- a/drivers/net/ntb_netdev.c ++++ b/drivers/net/ntb_netdev.c +@@ -137,7 +137,7 @@ static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data, + enqueue_again: + rc = ntb_transport_rx_enqueue(qp, skb, skb->data, ndev->mtu + ETH_HLEN); + if (rc) { +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + ndev->stats.rx_errors++; + ndev->stats.rx_fifo_errors++; + } +@@ -192,7 +192,7 @@ static void ntb_netdev_tx_handler(struct ntb_transport_qp *qp, void *qp_data, + ndev->stats.tx_aborted_errors++; + } + +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + + if (ntb_transport_tx_free_entry(dev->qp) >= tx_start) { + /* Make sure anybody stopping the queue after this sees the new +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 9206c660a72ed..d4c821c8cf57c 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -1743,6 +1743,8 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + int len; + unsigned char *cp; + ++ skb->dev = ppp->dev; ++ + if (proto < 0x8000) { + #ifdef CONFIG_PPP_FILTER + /* check if we should pass this packet */ +diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c +index 6a212c085435b..5b01642ca44e0 100644 +--- a/drivers/net/wan/farsync.c ++++ b/drivers/net/wan/farsync.c +@@ -2545,6 +2545,7 @@ fst_remove_one(struct pci_dev *pdev) + struct net_device *dev = port_to_dev(&card->ports[i]); + + unregister_hdlc_device(dev); ++ free_netdev(dev); + } + + fst_disable_intr(card); +@@ -2564,6 +2565,7 @@ fst_remove_one(struct pci_dev *pdev) + card->tx_dma_handle_card); + } + fst_card_array[card->card_no] = NULL; ++ kfree(card); + } + + static struct pci_driver fst_driver = { +diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c +index 6f937d2cc1263..ce3d613fa36c4 100644 +--- a/drivers/net/wireless/ath/ar5523/ar5523.c ++++ b/drivers/net/wireless/ath/ar5523/ar5523.c +@@ -241,6 +241,11 @@ static void ar5523_cmd_tx_cb(struct urb *urb) + } + } + ++static void ar5523_cancel_tx_cmd(struct ar5523 *ar) ++{ ++ usb_kill_urb(ar->tx_cmd.urb_tx); ++} ++ + static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata, + int ilen, void *odata, int olen, int flags) + { +@@ -280,6 +285,7 @@ static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata, + } + + if (!wait_for_completion_timeout(&cmd->done, 2 * HZ)) { ++ ar5523_cancel_tx_cmd(ar); + cmd->odata = NULL; + ar5523_err(ar, "timeout waiting for command %02x reply\n", + code); +diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c +index 400f332a7ff01..5eb131ab916fd 100644 +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -99,6 +99,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, ++ .delay_unmap_buffer = false, + }, + { + .id = QCA988X_HW_2_0_VERSION, +@@ -138,6 +139,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, ++ .delay_unmap_buffer = false, + }, + { + .id = QCA9887_HW_1_0_VERSION, +@@ -178,6 +180,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, ++ .delay_unmap_buffer = false, + }, + { + .id = QCA6174_HW_3_2_VERSION, +@@ -213,6 +216,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .dynamic_sar_support = true, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, ++ .delay_unmap_buffer = false, + }, + { + .id = QCA6174_HW_2_1_VERSION, +@@ -252,6 +256,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, ++ .delay_unmap_buffer = false, + }, + { + .id = QCA6174_HW_2_1_VERSION, +@@ -291,6 +296,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, ++ .delay_unmap_buffer = false, + }, + { + .id = QCA6174_HW_3_0_VERSION, +@@ -330,6 +336,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, ++ .delay_unmap_buffer = false, + }, + { + .id = QCA6174_HW_3_2_VERSION, +@@ -373,6 +380,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .dynamic_sar_support = true, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, ++ .delay_unmap_buffer = false, + }, + { + .id = QCA99X0_HW_2_0_DEV_VERSION, +@@ -418,6 +426,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, ++ .delay_unmap_buffer = false, + }, + { + .id = QCA9984_HW_1_0_DEV_VERSION, +@@ -470,6 +479,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, ++ .delay_unmap_buffer = false, + }, + { + .id = QCA9888_HW_2_0_DEV_VERSION, +@@ -519,6 +529,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, ++ .delay_unmap_buffer = false, + }, + { + .id = QCA9377_HW_1_0_DEV_VERSION, +@@ -558,6 +569,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, ++ .delay_unmap_buffer = false, + }, + { + .id = QCA9377_HW_1_1_DEV_VERSION, +@@ -599,6 +611,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, ++ .delay_unmap_buffer = false, + }, + { + .id = QCA9377_HW_1_1_DEV_VERSION, +@@ -631,6 +644,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, ++ .delay_unmap_buffer = false, + }, + { + .id = QCA4019_HW_1_0_DEV_VERSION, +@@ -677,6 +691,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, ++ .delay_unmap_buffer = false, + }, + { + .id = WCN3990_HW_1_0_DEV_VERSION, +@@ -709,6 +724,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .dynamic_sar_support = true, + .hw_restart_disconnect = true, + .use_fw_tx_credits = false, ++ .delay_unmap_buffer = true, + }, + }; + +diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c +index 6d1784f74bea4..5bfeecb95fca2 100644 +--- a/drivers/net/wireless/ath/ath10k/htc.c ++++ b/drivers/net/wireless/ath/ath10k/htc.c +@@ -56,6 +56,15 @@ void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep, + ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: ep %d skb %pK\n", __func__, + ep->eid, skb); + ++ /* A corner case where the copy completion is reaching to host but still ++ * copy engine is processing it due to which host unmaps corresponding ++ * memory and causes SMMU fault, hence as workaround adding delay ++ * the unmapping memory to avoid SMMU faults. ++ */ ++ if (ar->hw_params.delay_unmap_buffer && ++ ep->ul_pipe_id == 3) ++ mdelay(2); ++ + hdr = (struct ath10k_htc_hdr *)skb->data; + ath10k_htc_restore_tx_skb(ep->htc, skb); + +diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h +index 1b99f3a39a113..9643031a4427a 100644 +--- a/drivers/net/wireless/ath/ath10k/hw.h ++++ b/drivers/net/wireless/ath/ath10k/hw.h +@@ -637,6 +637,8 @@ struct ath10k_hw_params { + bool hw_restart_disconnect; + + bool use_fw_tx_credits; ++ ++ bool delay_unmap_buffer; + }; + + struct htt_resp; +diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c +index e56c6a6b13791..728d607289c36 100644 +--- a/drivers/net/wireless/ath/ath10k/pci.c ++++ b/drivers/net/wireless/ath/ath10k/pci.c +@@ -3792,18 +3792,22 @@ static struct pci_driver ath10k_pci_driver = { + + static int __init ath10k_pci_init(void) + { +- int ret; ++ int ret1, ret2; + +- ret = pci_register_driver(&ath10k_pci_driver); +- if (ret) ++ ret1 = pci_register_driver(&ath10k_pci_driver); ++ if (ret1) + printk(KERN_ERR "failed to register ath10k pci driver: %d\n", +- ret); ++ ret1); + +- ret = ath10k_ahb_init(); +- if (ret) +- printk(KERN_ERR "ahb init failed: %d\n", ret); ++ ret2 = ath10k_ahb_init(); ++ if (ret2) ++ printk(KERN_ERR "ahb init failed: %d\n", ret2); + +- return ret; ++ if (ret1 && ret2) ++ return ret1; ++ ++ /* registered to at least one bus */ ++ return 0; + } + module_init(ath10k_pci_init); + +diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h +index cf2f52cc4e30d..c20e84e031fad 100644 +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -505,6 +505,8 @@ struct ath11k_sta { + u64 ps_start_jiffies; + u64 ps_total_duration; + bool peer_current_ps_valid; ++ ++ u32 bw_prev; + }; + + #define ATH11K_MIN_5G_FREQ 4150 +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index 2d1e3fd9b526c..ef7617802491e 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -4215,10 +4215,11 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) + const u8 *ht_mcs_mask; + const u16 *vht_mcs_mask; + const u16 *he_mcs_mask; +- u32 changed, bw, nss, smps; ++ u32 changed, bw, nss, smps, bw_prev; + int err, num_vht_rates, num_he_rates; + const struct cfg80211_bitrate_mask *mask; + struct peer_assoc_params peer_arg; ++ enum wmi_phy_mode peer_phymode; + + arsta = container_of(wk, struct ath11k_sta, update_wk); + sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv); +@@ -4239,6 +4240,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) + arsta->changed = 0; + + bw = arsta->bw; ++ bw_prev = arsta->bw_prev; + nss = arsta->nss; + smps = arsta->smps; + +@@ -4252,26 +4254,57 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) + ath11k_mac_max_he_nss(he_mcs_mask))); + + if (changed & IEEE80211_RC_BW_CHANGED) { +- /* Send peer assoc command before set peer bandwidth param to +- * avoid the mismatch between the peer phymode and the peer +- * bandwidth. +- */ +- ath11k_peer_assoc_prepare(ar, arvif->vif, sta, &peer_arg, true); +- +- peer_arg.is_assoc = false; +- err = ath11k_wmi_send_peer_assoc_cmd(ar, &peer_arg); +- if (err) { +- ath11k_warn(ar->ab, "failed to send peer assoc for STA %pM vdev %i: %d\n", +- sta->addr, arvif->vdev_id, err); +- } else if (wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) { ++ /* Get the peer phymode */ ++ ath11k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg); ++ peer_phymode = peer_arg.peer_phymode; ++ ++ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac update sta %pM peer bw %d phymode %d\n", ++ sta->addr, bw, peer_phymode); ++ ++ if (bw > bw_prev) { ++ /* BW is upgraded. In this case we send WMI_PEER_PHYMODE ++ * followed by WMI_PEER_CHWIDTH ++ */ ++ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac BW upgrade for sta %pM new BW %d, old BW %d\n", ++ sta->addr, bw, bw_prev); ++ ++ err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, ++ WMI_PEER_PHYMODE, peer_phymode); ++ ++ if (err) { ++ ath11k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n", ++ sta->addr, peer_phymode, err); ++ goto err_rc_bw_changed; ++ } ++ + err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, + WMI_PEER_CHWIDTH, bw); ++ + if (err) + ath11k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n", + sta->addr, bw, err); + } else { +- ath11k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n", +- sta->addr, arvif->vdev_id); ++ /* BW is downgraded. In this case we send WMI_PEER_CHWIDTH ++ * followed by WMI_PEER_PHYMODE ++ */ ++ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac BW downgrade for sta %pM new BW %d,old BW %d\n", ++ sta->addr, bw, bw_prev); ++ ++ err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, ++ WMI_PEER_CHWIDTH, bw); ++ ++ if (err) { ++ ath11k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n", ++ sta->addr, bw, err); ++ goto err_rc_bw_changed; ++ } ++ ++ err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, ++ WMI_PEER_PHYMODE, peer_phymode); ++ ++ if (err) ++ ath11k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n", ++ sta->addr, peer_phymode, err); + } + } + +@@ -4352,6 +4385,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) + } + } + ++err_rc_bw_changed: + mutex_unlock(&ar->conf_mutex); + } + +@@ -4505,6 +4539,34 @@ exit: + return ret; + } + ++static u32 ath11k_mac_ieee80211_sta_bw_to_wmi(struct ath11k *ar, ++ struct ieee80211_sta *sta) ++{ ++ u32 bw = WMI_PEER_CHWIDTH_20MHZ; ++ ++ switch (sta->deflink.bandwidth) { ++ case IEEE80211_STA_RX_BW_20: ++ bw = WMI_PEER_CHWIDTH_20MHZ; ++ break; ++ case IEEE80211_STA_RX_BW_40: ++ bw = WMI_PEER_CHWIDTH_40MHZ; ++ break; ++ case IEEE80211_STA_RX_BW_80: ++ bw = WMI_PEER_CHWIDTH_80MHZ; ++ break; ++ case IEEE80211_STA_RX_BW_160: ++ bw = WMI_PEER_CHWIDTH_160MHZ; ++ break; ++ default: ++ ath11k_warn(ar->ab, "Invalid bandwidth %d for %pM\n", ++ sta->deflink.bandwidth, sta->addr); ++ bw = WMI_PEER_CHWIDTH_20MHZ; ++ break; ++ } ++ ++ return bw; ++} ++ + static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, +@@ -4590,6 +4652,12 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw, + if (ret) + ath11k_warn(ar->ab, "Failed to associate station: %pM\n", + sta->addr); ++ ++ spin_lock_bh(&ar->data_lock); ++ /* Set arsta bw and prev bw */ ++ arsta->bw = ath11k_mac_ieee80211_sta_bw_to_wmi(ar, sta); ++ arsta->bw_prev = arsta->bw; ++ spin_unlock_bh(&ar->data_lock); + } else if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTHORIZED) { + spin_lock_bh(&ar->ab->base_lock); +@@ -4713,28 +4781,8 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw, + spin_lock_bh(&ar->data_lock); + + if (changed & IEEE80211_RC_BW_CHANGED) { +- bw = WMI_PEER_CHWIDTH_20MHZ; +- +- switch (sta->deflink.bandwidth) { +- case IEEE80211_STA_RX_BW_20: +- bw = WMI_PEER_CHWIDTH_20MHZ; +- break; +- case IEEE80211_STA_RX_BW_40: +- bw = WMI_PEER_CHWIDTH_40MHZ; +- break; +- case IEEE80211_STA_RX_BW_80: +- bw = WMI_PEER_CHWIDTH_80MHZ; +- break; +- case IEEE80211_STA_RX_BW_160: +- bw = WMI_PEER_CHWIDTH_160MHZ; +- break; +- default: +- ath11k_warn(ar->ab, "Invalid bandwidth %d in rc update for %pM\n", +- sta->deflink.bandwidth, sta->addr); +- bw = WMI_PEER_CHWIDTH_20MHZ; +- break; +- } +- ++ bw = ath11k_mac_ieee80211_sta_bw_to_wmi(ar, sta); ++ arsta->bw_prev = arsta->bw; + arsta->bw = bw; + } + +diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c +index 51de2208b7899..8358fe08c2344 100644 +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -3087,6 +3087,9 @@ static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = { + sizeof(struct qmi_wlfw_fw_init_done_ind_msg_v01), + .fn = ath11k_qmi_msg_fw_init_done_cb, + }, ++ ++ /* end of list */ ++ {}, + }; + + static int ath11k_qmi_ops_new_server(struct qmi_handle *qmi_hdl, +diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c +index 4d9002a9d082c..1a2e0c7eeb023 100644 +--- a/drivers/net/wireless/ath/ath9k/hif_usb.c ++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c +@@ -708,14 +708,13 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) + struct rx_buf *rx_buf = (struct rx_buf *)urb->context; + struct hif_device_usb *hif_dev = rx_buf->hif_dev; + struct sk_buff *skb = rx_buf->skb; +- struct sk_buff *nskb; + int ret; + + if (!skb) + return; + + if (!hif_dev) +- goto free; ++ goto free_skb; + + switch (urb->status) { + case 0: +@@ -724,7 +723,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) + case -ECONNRESET: + case -ENODEV: + case -ESHUTDOWN: +- goto free; ++ goto free_skb; + default: + skb_reset_tail_pointer(skb); + skb_trim(skb, 0); +@@ -735,25 +734,27 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) + if (likely(urb->actual_length != 0)) { + skb_put(skb, urb->actual_length); + +- /* Process the command first */ ++ /* ++ * Process the command first. ++ * skb is either freed here or passed to be ++ * managed to another callback function. ++ */ + ath9k_htc_rx_msg(hif_dev->htc_handle, skb, + skb->len, USB_REG_IN_PIPE); + +- +- nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); +- if (!nskb) { ++ skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); ++ if (!skb) { + dev_err(&hif_dev->udev->dev, + "ath9k_htc: REG_IN memory allocation failure\n"); +- urb->context = NULL; +- return; ++ goto free_rx_buf; + } + +- rx_buf->skb = nskb; ++ rx_buf->skb = skb; + + usb_fill_int_urb(urb, hif_dev->udev, + usb_rcvintpipe(hif_dev->udev, + USB_REG_IN_PIPE), +- nskb->data, MAX_REG_IN_BUF_SIZE, ++ skb->data, MAX_REG_IN_BUF_SIZE, + ath9k_hif_usb_reg_in_cb, rx_buf, 1); + } + +@@ -762,12 +763,13 @@ resubmit: + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) { + usb_unanchor_urb(urb); +- goto free; ++ goto free_skb; + } + + return; +-free: ++free_skb: + kfree_skb(skb); ++free_rx_buf: + kfree(rx_buf); + urb->context = NULL; + } +@@ -780,14 +782,10 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) + spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); + list_for_each_entry_safe(tx_buf, tx_buf_tmp, + &hif_dev->tx.tx_buf, list) { +- usb_get_urb(tx_buf->urb); +- spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); +- usb_kill_urb(tx_buf->urb); + list_del(&tx_buf->list); + usb_free_urb(tx_buf->urb); + kfree(tx_buf->buf); + kfree(tx_buf); +- spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); + } + spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); + +@@ -1329,10 +1327,24 @@ static int send_eject_command(struct usb_interface *interface) + static int ath9k_hif_usb_probe(struct usb_interface *interface, + const struct usb_device_id *id) + { ++ struct usb_endpoint_descriptor *bulk_in, *bulk_out, *int_in, *int_out; + struct usb_device *udev = interface_to_usbdev(interface); ++ struct usb_host_interface *alt; + struct hif_device_usb *hif_dev; + int ret = 0; + ++ /* Verify the expected endpoints are present */ ++ alt = interface->cur_altsetting; ++ if (usb_find_common_endpoints(alt, &bulk_in, &bulk_out, &int_in, &int_out) < 0 || ++ usb_endpoint_num(bulk_in) != USB_WLAN_RX_PIPE || ++ usb_endpoint_num(bulk_out) != USB_WLAN_TX_PIPE || ++ usb_endpoint_num(int_in) != USB_REG_IN_PIPE || ++ usb_endpoint_num(int_out) != USB_REG_OUT_PIPE) { ++ dev_err(&udev->dev, ++ "ath9k_htc: Device endpoint numbers are not the expected ones\n"); ++ return -ENODEV; ++ } ++ + if (id->driver_info == STORAGE_DEVICE) + return send_eject_command(interface); + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +index 74020fa100659..22344e68fd597 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +@@ -305,8 +305,12 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) + brcmf_info("Firmware: %s %s\n", ri->chipname, buf); + + /* locate firmware version number for ethtool */ +- ptr = strrchr(buf, ' ') + 1; +- strscpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver)); ++ ptr = strrchr(buf, ' '); ++ if (!ptr) { ++ bphy_err(drvr, "Retrieving version number failed"); ++ goto done; ++ } ++ strscpy(ifp->drvr->fwver, ptr + 1, sizeof(ifp->drvr->fwver)); + + /* Query for 'clmver' to get CLM version info from firmware */ + memset(buf, 0, sizeof(buf)); +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +index f2207793f6e27..09d2f2dc2b46f 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +@@ -803,6 +803,11 @@ brcmf_fw_alloc_request(u32 chip, u32 chiprev, + u32 i, j; + char end = '\0'; + ++ if (chiprev >= BITS_PER_TYPE(u32)) { ++ brcmf_err("Invalid chip revision %u\n", chiprev); ++ return NULL; ++ } ++ + for (i = 0; i < table_size; i++) { + if (mapping_table[i].chipid == chip && + mapping_table[i].revmask & BIT(chiprev)) +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index 80083f9ea3116..5630f6e718e12 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -726,7 +726,7 @@ static int brcmf_pcie_exit_download_state(struct brcmf_pciedev_info *devinfo, + } + + if (!brcmf_chip_set_active(devinfo->ci, resetintr)) +- return -EINVAL; ++ return -EIO; + return 0; + } + +@@ -1218,6 +1218,10 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo) + BRCMF_NROF_H2D_COMMON_MSGRINGS; + max_completionrings = BRCMF_NROF_D2H_COMMON_MSGRINGS; + } ++ if (max_flowrings > 256) { ++ brcmf_err(bus, "invalid max_flowrings(%d)\n", max_flowrings); ++ return -EIO; ++ } + + if (devinfo->dma_idx_sz != 0) { + bufsz = (max_submissionrings + max_completionrings) * +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +index 465d95d837592..e265a2e411a09 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -3414,6 +3414,7 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus, + /* Take arm out of reset */ + if (!brcmf_chip_set_active(bus->ci, rstvec)) { + brcmf_err("error getting out of ARM core reset\n"); ++ bcmerror = -EIO; + goto err; + } + +diff --git a/drivers/net/wireless/intel/iwlwifi/mei/iwl-mei.h b/drivers/net/wireless/intel/iwlwifi/mei/iwl-mei.h +index 67122cfa22920..5409699c9a1fd 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mei/iwl-mei.h ++++ b/drivers/net/wireless/intel/iwlwifi/mei/iwl-mei.h +@@ -446,9 +446,10 @@ void iwl_mei_host_associated(const struct iwl_mei_conn_info *conn_info, + void iwl_mei_host_disassociated(void); + + /** +- * iwl_mei_device_down() - must be called when the device is down ++ * iwl_mei_device_state() - must be called when the device changes up/down state ++ * @up: true if the device is up, false otherwise. + */ +-void iwl_mei_device_down(void); ++void iwl_mei_device_state(bool up); + + #else + +@@ -497,7 +498,7 @@ static inline void iwl_mei_host_associated(const struct iwl_mei_conn_info *conn_ + static inline void iwl_mei_host_disassociated(void) + {} + +-static inline void iwl_mei_device_down(void) ++static inline void iwl_mei_device_state(bool up) + {} + + #endif /* CONFIG_IWLMEI */ +diff --git a/drivers/net/wireless/intel/iwlwifi/mei/main.c b/drivers/net/wireless/intel/iwlwifi/mei/main.c +index 357f14626cf43..c0142093c7682 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mei/main.c ++++ b/drivers/net/wireless/intel/iwlwifi/mei/main.c +@@ -147,9 +147,13 @@ struct iwl_mei_filters { + * to send CSME_OWNERSHIP_CONFIRMED when the driver completes its down + * flow. + * @link_prot_state: true when we are in link protection PASSIVE ++ * @device_down: true if the device is down. Used to remember to send ++ * CSME_OWNERSHIP_CONFIRMED when the driver is already down. + * @csa_throttle_end_wk: used when &csa_throttled is true + * @data_q_lock: protects the access to the data queues which are + * accessed without the mutex. ++ * @netdev_work: used to defer registering and unregistering of the netdev to ++ * avoid taking the rtnl lock in the SAP messages handlers. + * @sap_seq_no: the sequence number for the SAP messages + * @seq_no: the sequence number for the SAP messages + * @dbgfs_dir: the debugfs dir entry +@@ -167,8 +171,10 @@ struct iwl_mei { + bool csa_throttled; + bool csme_taking_ownership; + bool link_prot_state; ++ bool device_down; + struct delayed_work csa_throttle_end_wk; + spinlock_t data_q_lock; ++ struct work_struct netdev_work; + + atomic_t sap_seq_no; + atomic_t seq_no; +@@ -588,13 +594,38 @@ static rx_handler_result_t iwl_mei_rx_handler(struct sk_buff **pskb) + return res; + } + ++static void iwl_mei_netdev_work(struct work_struct *wk) ++{ ++ struct iwl_mei *mei = ++ container_of(wk, struct iwl_mei, netdev_work); ++ struct net_device *netdev; ++ ++ /* ++ * First take rtnl and only then the mutex to avoid an ABBA ++ * with iwl_mei_set_netdev() ++ */ ++ rtnl_lock(); ++ mutex_lock(&iwl_mei_mutex); ++ ++ netdev = rcu_dereference_protected(iwl_mei_cache.netdev, ++ lockdep_is_held(&iwl_mei_mutex)); ++ if (netdev) { ++ if (mei->amt_enabled) ++ netdev_rx_handler_register(netdev, iwl_mei_rx_handler, ++ mei); ++ else ++ netdev_rx_handler_unregister(netdev); ++ } ++ ++ mutex_unlock(&iwl_mei_mutex); ++ rtnl_unlock(); ++} ++ + static void + iwl_mei_handle_rx_start_ok(struct mei_cl_device *cldev, + const struct iwl_sap_me_msg_start_ok *rsp, + ssize_t len) + { +- struct iwl_mei *mei = mei_cldev_get_drvdata(cldev); +- + if (len != sizeof(*rsp)) { + dev_err(&cldev->dev, + "got invalid SAP_ME_MSG_START_OK from CSME firmware\n"); +@@ -613,13 +644,10 @@ iwl_mei_handle_rx_start_ok(struct mei_cl_device *cldev, + + mutex_lock(&iwl_mei_mutex); + set_bit(IWL_MEI_STATUS_SAP_CONNECTED, &iwl_mei_status); +- /* wifi driver has registered already */ +- if (iwl_mei_cache.ops) { +- iwl_mei_send_sap_msg(mei->cldev, +- SAP_MSG_NOTIF_WIFIDR_UP); +- iwl_mei_cache.ops->sap_connected(iwl_mei_cache.priv); +- } +- ++ /* ++ * We'll receive AMT_STATE SAP message in a bit and ++ * that will continue the flow ++ */ + mutex_unlock(&iwl_mei_mutex); + } + +@@ -712,6 +740,13 @@ static void iwl_mei_set_init_conf(struct iwl_mei *mei) + .val = cpu_to_le32(iwl_mei_cache.rf_kill), + }; + ++ /* wifi driver has registered already */ ++ if (iwl_mei_cache.ops) { ++ iwl_mei_send_sap_msg(mei->cldev, ++ SAP_MSG_NOTIF_WIFIDR_UP); ++ iwl_mei_cache.ops->sap_connected(iwl_mei_cache.priv); ++ } ++ + iwl_mei_send_sap_msg(mei->cldev, SAP_MSG_NOTIF_WHO_OWNS_NIC); + + if (iwl_mei_cache.conn_info) { +@@ -738,38 +773,23 @@ static void iwl_mei_handle_amt_state(struct mei_cl_device *cldev, + const struct iwl_sap_msg_dw *dw) + { + struct iwl_mei *mei = mei_cldev_get_drvdata(cldev); +- struct net_device *netdev; + +- /* +- * First take rtnl and only then the mutex to avoid an ABBA +- * with iwl_mei_set_netdev() +- */ +- rtnl_lock(); + mutex_lock(&iwl_mei_mutex); + +- netdev = rcu_dereference_protected(iwl_mei_cache.netdev, +- lockdep_is_held(&iwl_mei_mutex)); +- + if (mei->amt_enabled == !!le32_to_cpu(dw->val)) + goto out; + + mei->amt_enabled = dw->val; + +- if (mei->amt_enabled) { +- if (netdev) +- netdev_rx_handler_register(netdev, iwl_mei_rx_handler, mei); +- ++ if (mei->amt_enabled) + iwl_mei_set_init_conf(mei); +- } else { +- if (iwl_mei_cache.ops) +- iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, false); +- if (netdev) +- netdev_rx_handler_unregister(netdev); +- } ++ else if (iwl_mei_cache.ops) ++ iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, false, false); ++ ++ schedule_work(&mei->netdev_work); + + out: + mutex_unlock(&iwl_mei_mutex); +- rtnl_unlock(); + } + + static void iwl_mei_handle_nic_owner(struct mei_cl_device *cldev, +@@ -798,14 +818,18 @@ static void iwl_mei_handle_csme_taking_ownership(struct mei_cl_device *cldev, + + mei->got_ownership = false; + +- /* +- * Remember to send CSME_OWNERSHIP_CONFIRMED when the wifi driver +- * is finished taking the device down. +- */ +- mei->csme_taking_ownership = true; ++ if (iwl_mei_cache.ops && !mei->device_down) { ++ /* ++ * Remember to send CSME_OWNERSHIP_CONFIRMED when the wifi ++ * driver is finished taking the device down. ++ */ ++ mei->csme_taking_ownership = true; + +- if (iwl_mei_cache.ops) +- iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, true); ++ iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, true, true); ++ } else { ++ iwl_mei_send_sap_msg(cldev, ++ SAP_MSG_NOTIF_CSME_OWNERSHIP_CONFIRMED); ++ } + } + + static void iwl_mei_handle_nvm(struct mei_cl_device *cldev, +@@ -1413,10 +1437,7 @@ void iwl_mei_host_associated(const struct iwl_mei_conn_info *conn_info, + + mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); + +- if (!mei) +- goto out; +- +- if (!mei->amt_enabled) ++ if (!mei && !mei->amt_enabled) + goto out; + + iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr); +@@ -1445,7 +1466,7 @@ void iwl_mei_host_disassociated(void) + + mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); + +- if (!mei) ++ if (!mei && !mei->amt_enabled) + goto out; + + iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr); +@@ -1481,7 +1502,7 @@ void iwl_mei_set_rfkill_state(bool hw_rfkill, bool sw_rfkill) + + mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); + +- if (!mei) ++ if (!mei && !mei->amt_enabled) + goto out; + + iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr); +@@ -1510,7 +1531,7 @@ void iwl_mei_set_nic_info(const u8 *mac_address, const u8 *nvm_address) + + mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); + +- if (!mei) ++ if (!mei && !mei->amt_enabled) + goto out; + + iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr); +@@ -1538,7 +1559,7 @@ void iwl_mei_set_country_code(u16 mcc) + + mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); + +- if (!mei) ++ if (!mei && !mei->amt_enabled) + goto out; + + iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr); +@@ -1564,7 +1585,7 @@ void iwl_mei_set_power_limit(const __le16 *power_limit) + + mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); + +- if (!mei) ++ if (!mei && !mei->amt_enabled) + goto out; + + memcpy(msg.sar_chain_info_table, power_limit, sizeof(msg.sar_chain_info_table)); +@@ -1616,7 +1637,7 @@ out: + } + EXPORT_SYMBOL_GPL(iwl_mei_set_netdev); + +-void iwl_mei_device_down(void) ++void iwl_mei_device_state(bool up) + { + struct iwl_mei *mei; + +@@ -1630,7 +1651,9 @@ void iwl_mei_device_down(void) + if (!mei) + goto out; + +- if (!mei->csme_taking_ownership) ++ mei->device_down = !up; ++ ++ if (up || !mei->csme_taking_ownership) + goto out; + + iwl_mei_send_sap_msg(mei->cldev, +@@ -1639,7 +1662,7 @@ void iwl_mei_device_down(void) + out: + mutex_unlock(&iwl_mei_mutex); + } +-EXPORT_SYMBOL_GPL(iwl_mei_device_down); ++EXPORT_SYMBOL_GPL(iwl_mei_device_state); + + int iwl_mei_register(void *priv, const struct iwl_mei_ops *ops) + { +@@ -1669,9 +1692,10 @@ int iwl_mei_register(void *priv, const struct iwl_mei_ops *ops) + + /* we have already a SAP connection */ + if (iwl_mei_is_connected()) { +- iwl_mei_send_sap_msg(mei->cldev, +- SAP_MSG_NOTIF_WIFIDR_UP); +- ops->rfkill(priv, mei->link_prot_state); ++ if (mei->amt_enabled) ++ iwl_mei_send_sap_msg(mei->cldev, ++ SAP_MSG_NOTIF_WIFIDR_UP); ++ ops->rfkill(priv, mei->link_prot_state, false); + } + } + ret = 0; +@@ -1818,9 +1842,11 @@ static int iwl_mei_probe(struct mei_cl_device *cldev, + iwl_mei_csa_throttle_end_wk); + init_waitqueue_head(&mei->get_ownership_wq); + spin_lock_init(&mei->data_q_lock); ++ INIT_WORK(&mei->netdev_work, iwl_mei_netdev_work); + + mei_cldev_set_drvdata(cldev, mei); + mei->cldev = cldev; ++ mei->device_down = true; + + do { + ret = iwl_mei_alloc_shared_mem(cldev); +@@ -1921,29 +1947,32 @@ static void iwl_mei_remove(struct mei_cl_device *cldev) + + mutex_lock(&iwl_mei_mutex); + +- /* +- * Tell CSME that we are going down so that it won't access the +- * memory anymore, make sure this message goes through immediately. +- */ +- mei->csa_throttled = false; +- iwl_mei_send_sap_msg(mei->cldev, +- SAP_MSG_NOTIF_HOST_GOES_DOWN); ++ if (mei->amt_enabled) { ++ /* ++ * Tell CSME that we are going down so that it won't access the ++ * memory anymore, make sure this message goes through immediately. ++ */ ++ mei->csa_throttled = false; ++ iwl_mei_send_sap_msg(mei->cldev, ++ SAP_MSG_NOTIF_HOST_GOES_DOWN); + +- for (i = 0; i < SEND_SAP_MAX_WAIT_ITERATION; i++) { +- if (!iwl_mei_host_to_me_data_pending(mei)) +- break; ++ for (i = 0; i < SEND_SAP_MAX_WAIT_ITERATION; i++) { ++ if (!iwl_mei_host_to_me_data_pending(mei)) ++ break; + +- msleep(5); +- } ++ msleep(20); ++ } + +- /* +- * If we couldn't make sure that CSME saw the HOST_GOES_DOWN message, +- * it means that it will probably keep reading memory that we are going +- * to unmap and free, expect IOMMU error messages. +- */ +- if (i == SEND_SAP_MAX_WAIT_ITERATION) +- dev_err(&mei->cldev->dev, +- "Couldn't get ACK from CSME on HOST_GOES_DOWN message\n"); ++ /* ++ * If we couldn't make sure that CSME saw the HOST_GOES_DOWN ++ * message, it means that it will probably keep reading memory ++ * that we are going to unmap and free, expect IOMMU error ++ * messages. ++ */ ++ if (i == SEND_SAP_MAX_WAIT_ITERATION) ++ dev_err(&mei->cldev->dev, ++ "Couldn't get ACK from CSME on HOST_GOES_DOWN message\n"); ++ } + + mutex_unlock(&iwl_mei_mutex); + +@@ -1976,6 +2005,7 @@ static void iwl_mei_remove(struct mei_cl_device *cldev) + */ + cancel_work_sync(&mei->send_csa_msg_wk); + cancel_delayed_work_sync(&mei->csa_throttle_end_wk); ++ cancel_work_sync(&mei->netdev_work); + + /* + * If someone waits for the ownership, let him know that we are going +diff --git a/drivers/net/wireless/intel/iwlwifi/mei/net.c b/drivers/net/wireless/intel/iwlwifi/mei/net.c +index 3472167c83707..eac46d1a397a8 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mei/net.c ++++ b/drivers/net/wireless/intel/iwlwifi/mei/net.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* +- * Copyright (C) 2021 Intel Corporation ++ * Copyright (C) 2021-2022 Intel Corporation + */ + + #include <uapi/linux/if_ether.h> +@@ -337,10 +337,14 @@ rx_handler_result_t iwl_mei_rx_filter(struct sk_buff *orig_skb, + if (!*pass_to_csme) + return RX_HANDLER_PASS; + +- if (ret == RX_HANDLER_PASS) ++ if (ret == RX_HANDLER_PASS) { + skb = skb_copy(orig_skb, GFP_ATOMIC); +- else ++ ++ if (!skb) ++ return RX_HANDLER_PASS; ++ } else { + skb = orig_skb; ++ } + + /* CSME wants the MAC header as well, push it back */ + skb_push(skb, skb->data - skb_mac_header(skb)); +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +index f041e77af059e..5de34edc51fe9 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +@@ -1665,6 +1665,8 @@ int iwl_mvm_up(struct iwl_mvm *mvm) + iwl_rfi_send_config_cmd(mvm, NULL); + } + ++ iwl_mvm_mei_device_state(mvm, true); ++ + IWL_DEBUG_INFO(mvm, "RT uCode started.\n"); + return 0; + error: +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +index 97cba526e4651..1ccb3cad7cdc1 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +@@ -2201,10 +2201,10 @@ static inline void iwl_mvm_mei_host_disassociated(struct iwl_mvm *mvm) + iwl_mei_host_disassociated(); + } + +-static inline void iwl_mvm_mei_device_down(struct iwl_mvm *mvm) ++static inline void iwl_mvm_mei_device_state(struct iwl_mvm *mvm, bool up) + { + if (mvm->mei_registered) +- iwl_mei_device_down(); ++ iwl_mei_device_state(up); + } + + static inline void iwl_mvm_mei_set_sw_rfkill_state(struct iwl_mvm *mvm) +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +index d2d42cd48af22..5b8e9a06f6d4a 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +@@ -1375,7 +1375,7 @@ void iwl_mvm_stop_device(struct iwl_mvm *mvm) + iwl_trans_stop_device(mvm->trans); + iwl_free_fw_paging(&mvm->fwrt); + iwl_fw_dump_conf_clear(&mvm->fwrt); +- iwl_mvm_mei_device_down(mvm); ++ iwl_mvm_mei_device_state(mvm, false); + } + + static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +index 86d20e13bf47a..ba944175546d4 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +@@ -1171,9 +1171,15 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, + /* From now on, we cannot access info->control */ + iwl_mvm_skb_prepare_status(skb, dev_cmd); + ++ /* ++ * The IV is introduced by the HW for new tx api, and it is not present ++ * in the skb, hence, don't tell iwl_mvm_mei_tx_copy_to_csme about the ++ * IV for those devices. ++ */ + if (ieee80211_is_data(fc)) + iwl_mvm_mei_tx_copy_to_csme(mvm, skb, +- info->control.hw_key ? ++ info->control.hw_key && ++ !iwl_mvm_has_new_tx_api(mvm) ? + info->control.hw_key->iv_len : 0); + + if (iwl_trans_tx(mvm->trans, skb, dev_cmd, txq_id)) +@@ -1206,6 +1212,7 @@ int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb, + struct sk_buff_head mpdus_skbs; + unsigned int payload_len; + int ret; ++ struct sk_buff *orig_skb = skb; + + if (WARN_ON_ONCE(!mvmsta)) + return -1; +@@ -1238,8 +1245,17 @@ int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb, + + ret = iwl_mvm_tx_mpdu(mvm, skb, &info, sta); + if (ret) { ++ /* Free skbs created as part of TSO logic that have not yet been dequeued */ + __skb_queue_purge(&mpdus_skbs); +- return ret; ++ /* skb here is not necessarily same as skb that entered this method, ++ * so free it explicitly. ++ */ ++ if (skb == orig_skb) ++ ieee80211_free_txskb(mvm->hw, skb); ++ else ++ kfree_skb(skb); ++ /* there was error, but we consumed skb one way or another, so return 0 */ ++ return 0; + } + } + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h +index 87db9498dea44..7bcf7a6b67df3 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76.h ++++ b/drivers/net/wireless/mediatek/mt76/mt76.h +@@ -1107,8 +1107,9 @@ static inline bool mt76_is_skb_pktid(u8 pktid) + static inline u8 mt76_tx_power_nss_delta(u8 nss) + { + static const u8 nss_delta[4] = { 0, 6, 9, 12 }; ++ u8 idx = nss - 1; + +- return nss_delta[nss - 1]; ++ return (idx < ARRAY_SIZE(nss_delta)) ? nss_delta[idx] : 0; + } + + static inline bool mt76_testmode_enabled(struct mt76_phy *phy) +diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +index 011fc9729b38c..025a237c1cce8 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +@@ -2834,6 +2834,9 @@ mt76_connac_mcu_send_ram_firmware(struct mt76_dev *dev, + len = le32_to_cpu(region->len); + addr = le32_to_cpu(region->addr); + ++ if (region->feature_set & FW_FEATURE_NON_DL) ++ goto next; ++ + if (region->feature_set & FW_FEATURE_OVERRIDE_ADDR) + override = addr; + +@@ -2850,6 +2853,7 @@ mt76_connac_mcu_send_ram_firmware(struct mt76_dev *dev, + return err; + } + ++next: + offset += len; + } + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +index 4b1a9811646fd..0bce0ce51be00 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +@@ -173,60 +173,50 @@ static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy) + void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev, + struct mt7915_phy *phy) + { +- u8 nss, nss_band, nss_band_max, *eeprom = dev->mt76.eeprom.data; ++ u8 path, nss, nss_max = 4, *eeprom = dev->mt76.eeprom.data; + struct mt76_phy *mphy = phy->mt76; +- bool ext_phy = phy != &dev->phy; + + mt7915_eeprom_parse_band_config(phy); + +- /* read tx/rx mask from eeprom */ ++ /* read tx/rx path from eeprom */ + if (is_mt7915(&dev->mt76)) { +- nss = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH, +- eeprom[MT_EE_WIFI_CONF]); ++ path = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH, ++ eeprom[MT_EE_WIFI_CONF]); + } else { +- nss = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH, +- eeprom[MT_EE_WIFI_CONF + phy->band_idx]); ++ path = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH, ++ eeprom[MT_EE_WIFI_CONF + phy->band_idx]); + } + +- if (!nss || nss > 4) +- nss = 4; ++ if (!path || path > 4) ++ path = 4; + + /* read tx/rx stream */ +- nss_band = nss; +- ++ nss = path; + if (dev->dbdc_support) { + if (is_mt7915(&dev->mt76)) { +- nss_band = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B0, +- eeprom[MT_EE_WIFI_CONF + 3]); ++ path = min_t(u8, path, 2); ++ nss = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B0, ++ eeprom[MT_EE_WIFI_CONF + 3]); + if (phy->band_idx) +- nss_band = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B1, +- eeprom[MT_EE_WIFI_CONF + 3]); ++ nss = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B1, ++ eeprom[MT_EE_WIFI_CONF + 3]); + } else { +- nss_band = FIELD_GET(MT_EE_WIFI_CONF_STREAM_NUM, +- eeprom[MT_EE_WIFI_CONF + 2 + phy->band_idx]); ++ nss = FIELD_GET(MT_EE_WIFI_CONF_STREAM_NUM, ++ eeprom[MT_EE_WIFI_CONF + 2 + phy->band_idx]); + } + +- nss_band_max = is_mt7986(&dev->mt76) ? +- MT_EE_NSS_MAX_DBDC_MA7986 : MT_EE_NSS_MAX_DBDC_MA7915; +- } else { +- nss_band_max = is_mt7986(&dev->mt76) ? +- MT_EE_NSS_MAX_MA7986 : MT_EE_NSS_MAX_MA7915; ++ if (!is_mt7986(&dev->mt76)) ++ nss_max = 2; + } + +- if (!nss_band || nss_band > nss_band_max) +- nss_band = nss_band_max; +- +- if (nss_band > nss) { +- dev_warn(dev->mt76.dev, +- "nss mismatch, nss(%d) nss_band(%d) band(%d) ext_phy(%d)\n", +- nss, nss_band, phy->band_idx, ext_phy); +- nss = nss_band; +- } ++ if (!nss) ++ nss = nss_max; ++ nss = min_t(u8, min_t(u8, nss_max, nss), path); + +- mphy->chainmask = BIT(nss) - 1; +- if (ext_phy) ++ mphy->chainmask = BIT(path) - 1; ++ if (phy->band_idx) + mphy->chainmask <<= dev->chainshift; +- mphy->antenna_mask = BIT(nss_band) - 1; ++ mphy->antenna_mask = BIT(nss) - 1; + dev->chainmask |= mphy->chainmask; + dev->chainshift = hweight8(dev->mphy.chainmask); + } +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h +index 7578ac6d0be62..f3e56817d36e9 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h +@@ -58,11 +58,6 @@ enum mt7915_eeprom_field { + #define MT_EE_RATE_DELTA_SIGN BIT(6) + #define MT_EE_RATE_DELTA_EN BIT(7) + +-#define MT_EE_NSS_MAX_MA7915 4 +-#define MT_EE_NSS_MAX_DBDC_MA7915 2 +-#define MT_EE_NSS_MAX_MA7986 4 +-#define MT_EE_NSS_MAX_DBDC_MA7986 4 +- + enum mt7915_adie_sku { + MT7976_ONE_ADIE_DBDC = 0x7, + MT7975_ONE_ADIE = 0x8, +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +index a4bcc617c1a34..e6bf6e04d4b9c 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +@@ -1151,7 +1151,7 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy) + FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); + u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28); +- int offset; ++ int eifs_ofdm = 360, sifs = 10, offset; + bool a_band = !(phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ); + + if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) +@@ -1169,17 +1169,26 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy) + reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); + ++ if (!is_mt7915(&dev->mt76)) { ++ if (!a_band) { ++ mt76_wr(dev, MT_TMAC_ICR1(phy->band_idx), ++ FIELD_PREP(MT_IFS_EIFS_CCK, 314)); ++ eifs_ofdm = 78; ++ } else { ++ eifs_ofdm = 84; ++ } ++ } else if (a_band) { ++ sifs = 16; ++ } ++ + mt76_wr(dev, MT_TMAC_CDTR(phy->band_idx), cck + reg_offset); + mt76_wr(dev, MT_TMAC_ODTR(phy->band_idx), ofdm + reg_offset); + mt76_wr(dev, MT_TMAC_ICR0(phy->band_idx), +- FIELD_PREP(MT_IFS_EIFS_OFDM, a_band ? 84 : 78) | ++ FIELD_PREP(MT_IFS_EIFS_OFDM, eifs_ofdm) | + FIELD_PREP(MT_IFS_RIFS, 2) | +- FIELD_PREP(MT_IFS_SIFS, 10) | ++ FIELD_PREP(MT_IFS_SIFS, sifs) | + FIELD_PREP(MT_IFS_SLOT, phy->slottime)); + +- mt76_wr(dev, MT_TMAC_ICR1(phy->band_idx), +- FIELD_PREP(MT_IFS_EIFS_CCK, 314)); +- + if (phy->slottime < 20 || a_band) + val = MT7915_CFEND_RATE_DEFAULT; + else +@@ -1600,7 +1609,7 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy) + + aggr0 = phy->band_idx ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0; + if (is_mt7915(&dev->mt76)) { +- for (i = 0, aggr1 = aggr0 + 4; i < 4; i++) { ++ for (i = 0, aggr1 = aggr0 + 8; i < 4; i++) { + val = mt76_rr(dev, MT_MIB_MB_SDR1(phy->band_idx, (i << 4))); + mib->ba_miss_cnt += + FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val); +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c +index 728a879c3b008..3808ce1647d9e 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c +@@ -65,10 +65,17 @@ static void mt7915_put_hif2(struct mt7915_hif *hif) + + static struct mt7915_hif *mt7915_pci_init_hif2(struct pci_dev *pdev) + { ++ struct pci_dev *tmp_pdev; ++ + hif_idx++; +- if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7916, NULL) && +- !pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x790a, NULL)) +- return NULL; ++ ++ tmp_pdev = pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7916, NULL); ++ if (!tmp_pdev) { ++ tmp_pdev = pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x790a, NULL); ++ if (!tmp_pdev) ++ return NULL; ++ } ++ pci_dev_put(tmp_pdev); + + writel(hif_idx | MT_PCIE_RECOG_ID_SEM, + pcim_iomap_table(pdev)[0] + MT_PCIE_RECOG_ID); +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c +index dcdb3cf04ac1b..4ad66b3443838 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c +@@ -37,6 +37,7 @@ mt7921_regd_notifier(struct wiphy *wiphy, + + memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2)); + dev->mt76.region = request->dfs_region; ++ dev->country_ie_env = request->country_ie_env; + + mt7921_mutex_acquire(dev); + mt7921_mcu_set_clc(dev, request->alpha2, request->country_ie_env); +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +index 650ab97ae0524..1c0d8cf19b8eb 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +@@ -396,6 +396,27 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) + if (v0 & MT_PRXV_HT_AD_CODE) + status->enc_flags |= RX_ENC_FLAG_LDPC; + ++ ret = mt76_connac2_mac_fill_rx_rate(&dev->mt76, status, sband, ++ rxv, &mode); ++ if (ret < 0) ++ return ret; ++ ++ if (rxd1 & MT_RXD1_NORMAL_GROUP_5) { ++ rxd += 6; ++ if ((u8 *)rxd - skb->data >= skb->len) ++ return -EINVAL; ++ ++ rxv = rxd; ++ /* Monitor mode would use RCPI described in GROUP 5 ++ * instead. ++ */ ++ v1 = le32_to_cpu(rxv[0]); ++ ++ rxd += 12; ++ if ((u8 *)rxd - skb->data >= skb->len) ++ return -EINVAL; ++ } ++ + status->chains = mphy->antenna_mask; + status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, v1); + status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, v1); +@@ -410,17 +431,6 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) + status->signal = max(status->signal, + status->chain_signal[i]); + } +- +- ret = mt76_connac2_mac_fill_rx_rate(&dev->mt76, status, sband, +- rxv, &mode); +- if (ret < 0) +- return ret; +- +- if (rxd1 & MT_RXD1_NORMAL_GROUP_5) { +- rxd += 18; +- if ((u8 *)rxd - skb->data >= skb->len) +- return -EINVAL; +- } + } + + amsdu_info = FIELD_GET(MT_RXD4_NORMAL_PAYLOAD_FORMAT, rxd4); +@@ -974,7 +984,7 @@ void mt7921_mac_update_mib_stats(struct mt7921_phy *phy) + mib->tx_amsdu_cnt += val; + } + +- for (i = 0, aggr1 = aggr0 + 4; i < 4; i++) { ++ for (i = 0, aggr1 = aggr0 + 8; i < 4; i++) { + u32 val2; + + val = mt76_rr(dev, MT_TX_AGG_CNT(0, i)); +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c +index 7e409ac7d9a82..111d9221b94f5 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c +@@ -1504,7 +1504,13 @@ static int mt7921_set_sar_specs(struct ieee80211_hw *hw, + int err; + + mt7921_mutex_acquire(dev); ++ err = mt7921_mcu_set_clc(dev, dev->mt76.alpha2, ++ dev->country_ie_env); ++ if (err < 0) ++ goto out; ++ + err = mt7921_set_tx_sar_pwr(hw, sar); ++out: + mt7921_mutex_release(dev); + + return err; +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +index eaba114a9c7e4..d36b940c0a07a 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +@@ -171,7 +171,7 @@ struct mt7921_clc { + u8 type; + u8 rsv[8]; + u8 data[]; +-}; ++} __packed; + + struct mt7921_phy { + struct mt76_phy *mt76; +@@ -244,6 +244,8 @@ struct mt7921_dev { + struct work_struct ipv6_ns_work; + /* IPv6 addresses for WoWLAN */ + struct sk_buff_head ipv6_ns_list; ++ ++ enum environment_cap country_ie_env; + }; + + enum { +diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c +index 4c4033bb1bb35..0597df2729a62 100644 +--- a/drivers/net/wireless/mediatek/mt76/usb.c ++++ b/drivers/net/wireless/mediatek/mt76/usb.c +@@ -766,6 +766,9 @@ static void mt76u_status_worker(struct mt76_worker *w) + struct mt76_queue *q; + int i; + ++ if (!test_bit(MT76_STATE_RUNNING, &dev->phy.state)) ++ return; ++ + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + q = dev->phy.q_tx[i]; + if (!q) +@@ -785,11 +788,11 @@ static void mt76u_status_worker(struct mt76_worker *w) + wake_up(&dev->tx_wait); + + mt76_worker_schedule(&dev->tx_worker); +- +- if (dev->drv->tx_status_data && +- !test_and_set_bit(MT76_READING_STATS, &dev->phy.state)) +- queue_work(dev->wq, &dev->usb.stat_work); + } ++ ++ if (dev->drv->tx_status_data && ++ !test_and_set_bit(MT76_READING_STATS, &dev->phy.state)) ++ queue_work(dev->wq, &dev->usb.stat_work); + } + + static void mt76u_tx_status_data(struct work_struct *work) +diff --git a/drivers/net/wireless/purelifi/plfxlc/usb.c b/drivers/net/wireless/purelifi/plfxlc/usb.c +index 39e54b3787d6a..76d0a778636a4 100644 +--- a/drivers/net/wireless/purelifi/plfxlc/usb.c ++++ b/drivers/net/wireless/purelifi/plfxlc/usb.c +@@ -247,6 +247,7 @@ error: + for (i = 0; i < RX_URBS_COUNT; i++) + free_rx_urb(urbs[i]); + } ++ kfree(urbs); + return r; + } + +diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +index 782b089a2e1ba..1ba66b8f70c95 100644 +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +@@ -1190,7 +1190,7 @@ struct rtl8723bu_c2h { + u8 bw; + } __packed ra_report; + }; +-}; ++} __packed; + + struct rtl8xxxu_fileops; + +diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +index ac641a56efb09..e9c1b62c9c3c2 100644 +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -1608,18 +1608,18 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) + { + struct device *dev = &priv->udev->dev; + struct ieee80211_hw *hw = priv->hw; +- u32 val32, bonding; ++ u32 val32, bonding, sys_cfg; + u16 val16; + +- val32 = rtl8xxxu_read32(priv, REG_SYS_CFG); +- priv->chip_cut = (val32 & SYS_CFG_CHIP_VERSION_MASK) >> ++ sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG); ++ priv->chip_cut = (sys_cfg & SYS_CFG_CHIP_VERSION_MASK) >> + SYS_CFG_CHIP_VERSION_SHIFT; +- if (val32 & SYS_CFG_TRP_VAUX_EN) { ++ if (sys_cfg & SYS_CFG_TRP_VAUX_EN) { + dev_info(dev, "Unsupported test chip\n"); + return -ENOTSUPP; + } + +- if (val32 & SYS_CFG_BT_FUNC) { ++ if (sys_cfg & SYS_CFG_BT_FUNC) { + if (priv->chip_cut >= 3) { + sprintf(priv->chip_name, "8723BU"); + priv->rtl_chip = RTL8723B; +@@ -1641,7 +1641,7 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) + if (val32 & MULTI_GPS_FUNC_EN) + priv->has_gps = 1; + priv->is_multi_func = 1; +- } else if (val32 & SYS_CFG_TYPE_ID) { ++ } else if (sys_cfg & SYS_CFG_TYPE_ID) { + bonding = rtl8xxxu_read32(priv, REG_HPON_FSM); + bonding &= HPON_FSM_BONDING_MASK; + if (priv->fops->tx_desc_size == +@@ -1692,7 +1692,7 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) + case RTL8188E: + case RTL8192E: + case RTL8723B: +- switch (val32 & SYS_CFG_VENDOR_EXT_MASK) { ++ switch (sys_cfg & SYS_CFG_VENDOR_EXT_MASK) { + case SYS_CFG_VENDOR_ID_TSMC: + sprintf(priv->chip_vendor, "TSMC"); + break; +@@ -1709,7 +1709,7 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) + } + break; + default: +- if (val32 & SYS_CFG_VENDOR_ID) { ++ if (sys_cfg & SYS_CFG_VENDOR_ID) { + sprintf(priv->chip_vendor, "UMC"); + priv->vendor_umc = 1; + } else { +@@ -4654,7 +4654,6 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + if (sta->deflink.ht_cap.cap & + (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20)) + sgi = 1; +- rcu_read_unlock(); + + highest_rate = fls(ramask) - 1; + if (highest_rate < DESC_RATE_MCS0) { +@@ -4679,6 +4678,7 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + else + rarpt->txrate.bw = RATE_INFO_BW_20; + } ++ rcu_read_unlock(); + bit_rate = cfg80211_calculate_bitrate(&rarpt->txrate); + rarpt->bit_rate = bit_rate; + rarpt->desc_rate = highest_rate; +@@ -5574,7 +5574,6 @@ static void rtl8xxxu_c2hcmd_callback(struct work_struct *work) + rarpt->txrate.flags = 0; + rate = c2h->ra_report.rate; + sgi = c2h->ra_report.sgi; +- bw = c2h->ra_report.bw; + + if (rate < DESC_RATE_MCS0) { + rarpt->txrate.legacy = +@@ -5591,8 +5590,13 @@ static void rtl8xxxu_c2hcmd_callback(struct work_struct *work) + RATE_INFO_FLAGS_SHORT_GI; + } + +- if (bw == RATE_INFO_BW_20) +- rarpt->txrate.bw |= RATE_INFO_BW_20; ++ if (skb->len >= offsetofend(typeof(*c2h), ra_report.bw)) { ++ if (c2h->ra_report.bw == RTL8XXXU_CHANNEL_WIDTH_40) ++ bw = RATE_INFO_BW_40; ++ else ++ bw = RATE_INFO_BW_20; ++ rarpt->txrate.bw = bw; ++ } + } + bit_rate = cfg80211_calculate_bitrate(&rarpt->txrate); + rarpt->bit_rate = bit_rate; +diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c +index bc2994865372b..ad420d7ec8af9 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.c ++++ b/drivers/net/wireless/realtek/rtw89/core.c +@@ -2527,7 +2527,7 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, + } + + /* update cam aid mac_id net_type */ +- rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); ++ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c cam\n"); + return ret; +diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c +index 0508dfca8edf7..077fddc5fa1ea 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.c ++++ b/drivers/net/wireless/realtek/rtw89/mac.c +@@ -1429,10 +1429,8 @@ static int dle_mix_cfg(struct rtw89_dev *rtwdev, const struct rtw89_dle_mem *cfg + #define INVALID_QT_WCPU U16_MAX + #define SET_QUOTA_VAL(_min_x, _max_x, _module, _idx) \ + do { \ +- val = ((_min_x) & \ +- B_AX_ ## _module ## _MIN_SIZE_MASK) | \ +- (((_max_x) << 16) & \ +- B_AX_ ## _module ## _MAX_SIZE_MASK); \ ++ val = u32_encode_bits(_min_x, B_AX_ ## _module ## _MIN_SIZE_MASK) | \ ++ u32_encode_bits(_max_x, B_AX_ ## _module ## _MAX_SIZE_MASK); \ + rtw89_write32(rtwdev, \ + R_AX_ ## _module ## _QTA ## _idx ## _CFG, \ + val); \ +diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c +index 6a6bdc652e09e..c894a2b614eb1 100644 +--- a/drivers/net/wireless/realtek/rtw89/phy.c ++++ b/drivers/net/wireless/realtek/rtw89/phy.c +@@ -3139,7 +3139,7 @@ void rtw89_phy_env_monitor_track(struct rtw89_dev *rtwdev) + + static bool rtw89_physts_ie_page_valid(enum rtw89_phy_status_bitmap *ie_page) + { +- if (*ie_page > RTW89_PHYSTS_BITMAP_NUM || ++ if (*ie_page >= RTW89_PHYSTS_BITMAP_NUM || + *ie_page == RTW89_RSVD_9) + return false; + else if (*ie_page > RTW89_RSVD_9) +diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c +index 0f3a80f66b61c..ead4d4e043280 100644 +--- a/drivers/net/wireless/rsi/rsi_91x_core.c ++++ b/drivers/net/wireless/rsi/rsi_91x_core.c +@@ -466,7 +466,9 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb) + tid, 0); + } + } +- if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { ++ ++ if (IEEE80211_SKB_CB(skb)->control.flags & ++ IEEE80211_TX_CTRL_PORT_CTRL_PROTO) { + q_num = MGMT_SOFT_Q; + skb->priority = q_num; + } +diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c +index c61f83a7333b6..c7460fbba0142 100644 +--- a/drivers/net/wireless/rsi/rsi_91x_hal.c ++++ b/drivers/net/wireless/rsi/rsi_91x_hal.c +@@ -162,12 +162,16 @@ int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb) + u8 header_size; + u8 vap_id = 0; + u8 dword_align_bytes; ++ bool tx_eapol; + u16 seq_num; + + info = IEEE80211_SKB_CB(skb); + vif = info->control.vif; + tx_params = (struct skb_info *)info->driver_data; + ++ tx_eapol = IEEE80211_SKB_CB(skb)->control.flags & ++ IEEE80211_TX_CTRL_PORT_CTRL_PROTO; ++ + header_size = FRAME_DESC_SZ + sizeof(struct rsi_xtended_desc); + if (header_size > skb_headroom(skb)) { + rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__); +@@ -231,7 +235,7 @@ int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb) + } + } + +- if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { ++ if (tx_eapol) { + rsi_dbg(INFO_ZONE, "*** Tx EAPOL ***\n"); + + data_desc->frame_info = cpu_to_le16(RATE_INFO_ENABLE); +diff --git a/drivers/nfc/pn533/pn533.c b/drivers/nfc/pn533/pn533.c +index d9f6367b9993d..f0cac19005527 100644 +--- a/drivers/nfc/pn533/pn533.c ++++ b/drivers/nfc/pn533/pn533.c +@@ -1295,6 +1295,8 @@ static int pn533_poll_dep_complete(struct pn533 *dev, void *arg, + if (IS_ERR(resp)) + return PTR_ERR(resp); + ++ memset(&nfc_target, 0, sizeof(struct nfc_target)); ++ + rsp = (struct pn533_cmd_jump_dep_response *)resp->data; + + rc = rsp->status & PN533_CMD_RET_MASK; +@@ -1926,6 +1928,8 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, + + dev_dbg(dev->dev, "Creating new target\n"); + ++ memset(&nfc_target, 0, sizeof(struct nfc_target)); ++ + nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; + nfc_target.nfcid1_len = 10; + memcpy(nfc_target.nfcid1, rsp->nfcid3t, nfc_target.nfcid1_len); +diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c +index 7e3893d06babd..108b5022ceadc 100644 +--- a/drivers/nvme/host/core.c ++++ b/drivers/nvme/host/core.c +@@ -3049,7 +3049,7 @@ static int nvme_init_non_mdts_limits(struct nvme_ctrl *ctrl) + + id = kzalloc(sizeof(*id), GFP_KERNEL); + if (!id) +- return 0; ++ return -ENOMEM; + + c.identify.opcode = nvme_admin_identify; + c.identify.cns = NVME_ID_CNS_CS_CTRL; +@@ -3745,13 +3745,17 @@ static ssize_t nvme_ctrl_dhchap_secret_store(struct device *dev, + memcpy(dhchap_secret, buf, count); + nvme_auth_stop(ctrl); + if (strcmp(dhchap_secret, opts->dhchap_secret)) { ++ struct nvme_dhchap_key *key, *host_key; + int ret; + +- ret = nvme_auth_generate_key(dhchap_secret, &ctrl->host_key); ++ ret = nvme_auth_generate_key(dhchap_secret, &key); + if (ret) + return ret; + kfree(opts->dhchap_secret); + opts->dhchap_secret = dhchap_secret; ++ host_key = ctrl->host_key; ++ ctrl->host_key = key; ++ nvme_auth_free_key(host_key); + /* Key has changed; re-authentication with new key */ + nvme_auth_reset(ctrl); + } +@@ -3795,13 +3799,17 @@ static ssize_t nvme_ctrl_dhchap_ctrl_secret_store(struct device *dev, + memcpy(dhchap_secret, buf, count); + nvme_auth_stop(ctrl); + if (strcmp(dhchap_secret, opts->dhchap_ctrl_secret)) { ++ struct nvme_dhchap_key *key, *ctrl_key; + int ret; + +- ret = nvme_auth_generate_key(dhchap_secret, &ctrl->ctrl_key); ++ ret = nvme_auth_generate_key(dhchap_secret, &key); + if (ret) + return ret; + kfree(opts->dhchap_ctrl_secret); + opts->dhchap_ctrl_secret = dhchap_secret; ++ ctrl_key = ctrl->ctrl_key; ++ ctrl->ctrl_key = key; ++ nvme_auth_free_key(ctrl_key); + /* Key has changed; re-authentication with new key */ + nvme_auth_reset(ctrl); + } +@@ -4867,7 +4875,7 @@ EXPORT_SYMBOL_GPL(nvme_remove_admin_tag_set); + + int nvme_alloc_io_tag_set(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set, + const struct blk_mq_ops *ops, unsigned int flags, +- unsigned int cmd_size) ++ unsigned int nr_maps, unsigned int cmd_size) + { + int ret; + +@@ -4881,8 +4889,7 @@ int nvme_alloc_io_tag_set(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set, + set->driver_data = ctrl; + set->nr_hw_queues = ctrl->queue_count - 1; + set->timeout = NVME_IO_TIMEOUT; +- if (ops->map_queues) +- set->nr_maps = ctrl->opts->nr_poll_queues ? HCTX_MAX_TYPES : 2; ++ set->nr_maps = nr_maps; + ret = blk_mq_alloc_tag_set(set); + if (ret) + return ret; +diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c +index 5d57a042dbcad..20b0c29a9a341 100644 +--- a/drivers/nvme/host/fc.c ++++ b/drivers/nvme/host/fc.c +@@ -2903,7 +2903,7 @@ nvme_fc_create_io_queues(struct nvme_fc_ctrl *ctrl) + nvme_fc_init_io_queues(ctrl); + + ret = nvme_alloc_io_tag_set(&ctrl->ctrl, &ctrl->tag_set, +- &nvme_fc_mq_ops, BLK_MQ_F_SHOULD_MERGE, ++ &nvme_fc_mq_ops, BLK_MQ_F_SHOULD_MERGE, 1, + struct_size((struct nvme_fcp_op_w_sgl *)NULL, priv, + ctrl->lport->ops->fcprqst_priv_sz)); + if (ret) +diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h +index a29877217ee65..8a0db9e06dc65 100644 +--- a/drivers/nvme/host/nvme.h ++++ b/drivers/nvme/host/nvme.h +@@ -743,7 +743,7 @@ int nvme_alloc_admin_tag_set(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set, + void nvme_remove_admin_tag_set(struct nvme_ctrl *ctrl); + int nvme_alloc_io_tag_set(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set, + const struct blk_mq_ops *ops, unsigned int flags, +- unsigned int cmd_size); ++ unsigned int nr_maps, unsigned int cmd_size); + void nvme_remove_io_tag_set(struct nvme_ctrl *ctrl); + + void nvme_remove_namespaces(struct nvme_ctrl *ctrl); +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index 488ad7dabeb8e..115d81def5671 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -35,7 +35,7 @@ + #define SQ_SIZE(q) ((q)->q_depth << (q)->sqes) + #define CQ_SIZE(q) ((q)->q_depth * sizeof(struct nvme_completion)) + +-#define SGES_PER_PAGE (PAGE_SIZE / sizeof(struct nvme_sgl_desc)) ++#define SGES_PER_PAGE (NVME_CTRL_PAGE_SIZE / sizeof(struct nvme_sgl_desc)) + + /* + * These can be higher, but we need to ensure that any command doesn't +@@ -144,9 +144,9 @@ struct nvme_dev { + mempool_t *iod_mempool; + + /* shadow doorbell buffer support: */ +- u32 *dbbuf_dbs; ++ __le32 *dbbuf_dbs; + dma_addr_t dbbuf_dbs_dma_addr; +- u32 *dbbuf_eis; ++ __le32 *dbbuf_eis; + dma_addr_t dbbuf_eis_dma_addr; + + /* host memory buffer support: */ +@@ -210,10 +210,10 @@ struct nvme_queue { + #define NVMEQ_SQ_CMB 1 + #define NVMEQ_DELETE_ERROR 2 + #define NVMEQ_POLLED 3 +- u32 *dbbuf_sq_db; +- u32 *dbbuf_cq_db; +- u32 *dbbuf_sq_ei; +- u32 *dbbuf_cq_ei; ++ __le32 *dbbuf_sq_db; ++ __le32 *dbbuf_cq_db; ++ __le32 *dbbuf_sq_ei; ++ __le32 *dbbuf_cq_ei; + struct completion delete_done; + }; + +@@ -340,11 +340,11 @@ static inline int nvme_dbbuf_need_event(u16 event_idx, u16 new_idx, u16 old) + } + + /* Update dbbuf and return true if an MMIO is required */ +-static bool nvme_dbbuf_update_and_check_event(u16 value, u32 *dbbuf_db, +- volatile u32 *dbbuf_ei) ++static bool nvme_dbbuf_update_and_check_event(u16 value, __le32 *dbbuf_db, ++ volatile __le32 *dbbuf_ei) + { + if (dbbuf_db) { +- u16 old_value; ++ u16 old_value, event_idx; + + /* + * Ensure that the queue is written before updating +@@ -352,8 +352,8 @@ static bool nvme_dbbuf_update_and_check_event(u16 value, u32 *dbbuf_db, + */ + wmb(); + +- old_value = *dbbuf_db; +- *dbbuf_db = value; ++ old_value = le32_to_cpu(*dbbuf_db); ++ *dbbuf_db = cpu_to_le32(value); + + /* + * Ensure that the doorbell is updated before reading the event +@@ -363,7 +363,8 @@ static bool nvme_dbbuf_update_and_check_event(u16 value, u32 *dbbuf_db, + */ + mb(); + +- if (!nvme_dbbuf_need_event(*dbbuf_ei, value, old_value)) ++ event_idx = le32_to_cpu(*dbbuf_ei); ++ if (!nvme_dbbuf_need_event(event_idx, value, old_value)) + return false; + } + +@@ -377,9 +378,9 @@ static bool nvme_dbbuf_update_and_check_event(u16 value, u32 *dbbuf_db, + */ + static int nvme_pci_npages_prp(void) + { +- unsigned nprps = DIV_ROUND_UP(NVME_MAX_KB_SZ + NVME_CTRL_PAGE_SIZE, +- NVME_CTRL_PAGE_SIZE); +- return DIV_ROUND_UP(8 * nprps, PAGE_SIZE - 8); ++ unsigned max_bytes = (NVME_MAX_KB_SZ * 1024) + NVME_CTRL_PAGE_SIZE; ++ unsigned nprps = DIV_ROUND_UP(max_bytes, NVME_CTRL_PAGE_SIZE); ++ return DIV_ROUND_UP(8 * nprps, NVME_CTRL_PAGE_SIZE - 8); + } + + /* +@@ -389,7 +390,7 @@ static int nvme_pci_npages_prp(void) + static int nvme_pci_npages_sgl(void) + { + return DIV_ROUND_UP(NVME_MAX_SEGS * sizeof(struct nvme_sgl_desc), +- PAGE_SIZE); ++ NVME_CTRL_PAGE_SIZE); + } + + static size_t nvme_pci_iod_alloc_size(void) +@@ -713,7 +714,7 @@ static void nvme_pci_sgl_set_seg(struct nvme_sgl_desc *sge, + sge->length = cpu_to_le32(entries * sizeof(*sge)); + sge->type = NVME_SGL_FMT_LAST_SEG_DESC << 4; + } else { +- sge->length = cpu_to_le32(PAGE_SIZE); ++ sge->length = cpu_to_le32(NVME_CTRL_PAGE_SIZE); + sge->type = NVME_SGL_FMT_SEG_DESC << 4; + } + } +diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c +index 6e079abb22ee9..a55d3e8b607d5 100644 +--- a/drivers/nvme/host/rdma.c ++++ b/drivers/nvme/host/rdma.c +@@ -798,7 +798,9 @@ static int nvme_rdma_alloc_tag_set(struct nvme_ctrl *ctrl) + NVME_RDMA_METADATA_SGL_SIZE; + + return nvme_alloc_io_tag_set(ctrl, &to_rdma_ctrl(ctrl)->tag_set, +- &nvme_rdma_mq_ops, BLK_MQ_F_SHOULD_MERGE, cmd_size); ++ &nvme_rdma_mq_ops, BLK_MQ_F_SHOULD_MERGE, ++ ctrl->opts->nr_poll_queues ? HCTX_MAX_TYPES : 2, ++ cmd_size); + } + + static void nvme_rdma_destroy_admin_queue(struct nvme_rdma_ctrl *ctrl) +diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c +index 9b47dcb2a7d97..83735c52d34a0 100644 +--- a/drivers/nvme/host/tcp.c ++++ b/drivers/nvme/host/tcp.c +@@ -1868,6 +1868,7 @@ static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new) + ret = nvme_alloc_io_tag_set(ctrl, &to_tcp_ctrl(ctrl)->tag_set, + &nvme_tcp_mq_ops, + BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING, ++ ctrl->opts->nr_poll_queues ? HCTX_MAX_TYPES : 2, + sizeof(struct nvme_tcp_request)); + if (ret) + goto out_free_io_queues; +diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c +index aecb5853f8da4..683b75a992b3d 100644 +--- a/drivers/nvme/target/core.c ++++ b/drivers/nvme/target/core.c +@@ -15,6 +15,7 @@ + + #include "nvmet.h" + ++struct kmem_cache *nvmet_bvec_cache; + struct workqueue_struct *buffered_io_wq; + struct workqueue_struct *zbd_wq; + static const struct nvmet_fabrics_ops *nvmet_transports[NVMF_TRTYPE_MAX]; +@@ -1631,26 +1632,28 @@ void nvmet_subsys_put(struct nvmet_subsys *subsys) + + static int __init nvmet_init(void) + { +- int error; ++ int error = -ENOMEM; + + nvmet_ana_group_enabled[NVMET_DEFAULT_ANA_GRPID] = 1; + ++ nvmet_bvec_cache = kmem_cache_create("nvmet-bvec", ++ NVMET_MAX_MPOOL_BVEC * sizeof(struct bio_vec), 0, ++ SLAB_HWCACHE_ALIGN, NULL); ++ if (!nvmet_bvec_cache) ++ return -ENOMEM; ++ + zbd_wq = alloc_workqueue("nvmet-zbd-wq", WQ_MEM_RECLAIM, 0); + if (!zbd_wq) +- return -ENOMEM; ++ goto out_destroy_bvec_cache; + + buffered_io_wq = alloc_workqueue("nvmet-buffered-io-wq", + WQ_MEM_RECLAIM, 0); +- if (!buffered_io_wq) { +- error = -ENOMEM; ++ if (!buffered_io_wq) + goto out_free_zbd_work_queue; +- } + + nvmet_wq = alloc_workqueue("nvmet-wq", WQ_MEM_RECLAIM, 0); +- if (!nvmet_wq) { +- error = -ENOMEM; ++ if (!nvmet_wq) + goto out_free_buffered_work_queue; +- } + + error = nvmet_init_discovery(); + if (error) +@@ -1669,6 +1672,8 @@ out_free_buffered_work_queue: + destroy_workqueue(buffered_io_wq); + out_free_zbd_work_queue: + destroy_workqueue(zbd_wq); ++out_destroy_bvec_cache: ++ kmem_cache_destroy(nvmet_bvec_cache); + return error; + } + +@@ -1680,6 +1685,7 @@ static void __exit nvmet_exit(void) + destroy_workqueue(nvmet_wq); + destroy_workqueue(buffered_io_wq); + destroy_workqueue(zbd_wq); ++ kmem_cache_destroy(nvmet_bvec_cache); + + BUILD_BUG_ON(sizeof(struct nvmf_disc_rsp_page_entry) != 1024); + BUILD_BUG_ON(sizeof(struct nvmf_disc_rsp_page_hdr) != 1024); +diff --git a/drivers/nvme/target/io-cmd-file.c b/drivers/nvme/target/io-cmd-file.c +index 64b47e2a46330..e55ec6fefd7f4 100644 +--- a/drivers/nvme/target/io-cmd-file.c ++++ b/drivers/nvme/target/io-cmd-file.c +@@ -11,7 +11,6 @@ + #include <linux/fs.h> + #include "nvmet.h" + +-#define NVMET_MAX_MPOOL_BVEC 16 + #define NVMET_MIN_MPOOL_OBJ 16 + + void nvmet_file_ns_revalidate(struct nvmet_ns *ns) +@@ -26,8 +25,6 @@ void nvmet_file_ns_disable(struct nvmet_ns *ns) + flush_workqueue(buffered_io_wq); + mempool_destroy(ns->bvec_pool); + ns->bvec_pool = NULL; +- kmem_cache_destroy(ns->bvec_cache); +- ns->bvec_cache = NULL; + fput(ns->file); + ns->file = NULL; + } +@@ -59,16 +56,8 @@ int nvmet_file_ns_enable(struct nvmet_ns *ns) + ns->blksize_shift = min_t(u8, + file_inode(ns->file)->i_blkbits, 12); + +- ns->bvec_cache = kmem_cache_create("nvmet-bvec", +- NVMET_MAX_MPOOL_BVEC * sizeof(struct bio_vec), +- 0, SLAB_HWCACHE_ALIGN, NULL); +- if (!ns->bvec_cache) { +- ret = -ENOMEM; +- goto err; +- } +- + ns->bvec_pool = mempool_create(NVMET_MIN_MPOOL_OBJ, mempool_alloc_slab, +- mempool_free_slab, ns->bvec_cache); ++ mempool_free_slab, nvmet_bvec_cache); + + if (!ns->bvec_pool) { + ret = -ENOMEM; +@@ -77,9 +66,10 @@ int nvmet_file_ns_enable(struct nvmet_ns *ns) + + return ret; + err: ++ fput(ns->file); ++ ns->file = NULL; + ns->size = 0; + ns->blksize_shift = 0; +- nvmet_file_ns_disable(ns); + return ret; + } + +diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c +index b45fe3adf015f..08c583258e90f 100644 +--- a/drivers/nvme/target/loop.c ++++ b/drivers/nvme/target/loop.c +@@ -494,7 +494,7 @@ static int nvme_loop_create_io_queues(struct nvme_loop_ctrl *ctrl) + return ret; + + ret = nvme_alloc_io_tag_set(&ctrl->ctrl, &ctrl->tag_set, +- &nvme_loop_mq_ops, BLK_MQ_F_SHOULD_MERGE, ++ &nvme_loop_mq_ops, BLK_MQ_F_SHOULD_MERGE, 1, + sizeof(struct nvme_loop_iod) + + NVME_INLINE_SG_CNT * sizeof(struct scatterlist)); + if (ret) +diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h +index dfe3894205aa7..bda1c1f71f394 100644 +--- a/drivers/nvme/target/nvmet.h ++++ b/drivers/nvme/target/nvmet.h +@@ -77,7 +77,6 @@ struct nvmet_ns { + + struct completion disable_done; + mempool_t *bvec_pool; +- struct kmem_cache *bvec_cache; + + int use_p2pmem; + struct pci_dev *p2p_dev; +@@ -393,6 +392,8 @@ struct nvmet_req { + u64 error_slba; + }; + ++#define NVMET_MAX_MPOOL_BVEC 16 ++extern struct kmem_cache *nvmet_bvec_cache; + extern struct workqueue_struct *buffered_io_wq; + extern struct workqueue_struct *zbd_wq; + extern struct workqueue_struct *nvmet_wq; +diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c +index 79af5140af8bf..adc0958755d66 100644 +--- a/drivers/nvme/target/passthru.c ++++ b/drivers/nvme/target/passthru.c +@@ -334,14 +334,13 @@ static void nvmet_passthru_execute_cmd(struct nvmet_req *req) + } + + /* +- * If there are effects for the command we are about to execute, or +- * an end_req function we need to use nvme_execute_passthru_rq() +- * synchronously in a work item seeing the end_req function and +- * nvme_passthru_end() can't be called in the request done callback +- * which is typically in interrupt context. ++ * If a command needs post-execution fixups, or there are any ++ * non-trivial effects, make sure to execute the command synchronously ++ * in a workqueue so that nvme_passthru_end gets called. + */ + effects = nvme_command_effects(ctrl, ns, req->cmd->common.opcode); +- if (req->p.use_workqueue || effects) { ++ if (req->p.use_workqueue || ++ (effects & ~(NVME_CMD_EFFECTS_CSUPP | NVME_CMD_EFFECTS_LBCC))) { + INIT_WORK(&req->p.work, nvmet_passthru_execute_cmd_work); + req->p.rq = rq; + queue_work(nvmet_wq, &req->p.work); +diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c +index bd8ff4df723da..ed4e6c144a681 100644 +--- a/drivers/of/overlay.c ++++ b/drivers/of/overlay.c +@@ -545,7 +545,7 @@ static int find_dup_cset_node_entry(struct overlay_changeset *ovcs, + + fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np); + fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np); +- node_path_match = !strcmp(fn_1, fn_2); ++ node_path_match = !fn_1 || !fn_2 || !strcmp(fn_1, fn_2); + kfree(fn_1); + kfree(fn_2); + if (node_path_match) { +@@ -580,7 +580,7 @@ static int find_dup_cset_prop(struct overlay_changeset *ovcs, + + fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np); + fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np); +- node_path_match = !strcmp(fn_1, fn_2); ++ node_path_match = !fn_1 || !fn_2 || !strcmp(fn_1, fn_2); + kfree(fn_1); + kfree(fn_2); + if (node_path_match && +diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c +index 2616585ca5f8a..1dde5c579edc8 100644 +--- a/drivers/pci/controller/dwc/pci-imx6.c ++++ b/drivers/pci/controller/dwc/pci-imx6.c +@@ -952,12 +952,6 @@ static int imx6_pcie_host_init(struct dw_pcie_rp *pp) + } + } + +- ret = imx6_pcie_deassert_core_reset(imx6_pcie); +- if (ret < 0) { +- dev_err(dev, "pcie deassert core reset failed: %d\n", ret); +- goto err_phy_off; +- } +- + if (imx6_pcie->phy) { + ret = phy_power_on(imx6_pcie->phy); + if (ret) { +@@ -965,6 +959,13 @@ static int imx6_pcie_host_init(struct dw_pcie_rp *pp) + goto err_phy_off; + } + } ++ ++ ret = imx6_pcie_deassert_core_reset(imx6_pcie); ++ if (ret < 0) { ++ dev_err(dev, "pcie deassert core reset failed: %d\n", ret); ++ goto err_phy_off; ++ } ++ + imx6_setup_phy_mpll(imx6_pcie); + + return 0; +diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c +index c6725c519a479..9e4d96e5a3f5a 100644 +--- a/drivers/pci/controller/dwc/pcie-designware.c ++++ b/drivers/pci/controller/dwc/pcie-designware.c +@@ -641,7 +641,7 @@ void dw_pcie_setup(struct dw_pcie *pci) + if (pci->n_fts[1]) { + val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); + val &= ~PORT_LOGIC_N_FTS_MASK; +- val |= pci->n_fts[pci->link_gen - 1]; ++ val |= pci->n_fts[1]; + dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val); + } + +diff --git a/drivers/pci/controller/pcie-mt7621.c b/drivers/pci/controller/pcie-mt7621.c +index 4bd1abf26008f..ee7aad09d6277 100644 +--- a/drivers/pci/controller/pcie-mt7621.c ++++ b/drivers/pci/controller/pcie-mt7621.c +@@ -466,7 +466,8 @@ static int mt7621_pcie_register_host(struct pci_host_bridge *host) + } + + static const struct soc_device_attribute mt7621_pcie_quirks_match[] = { +- { .soc_id = "mt7621", .revision = "E2" } ++ { .soc_id = "mt7621", .revision = "E2" }, ++ { /* sentinel */ } + }; + + static int mt7621_pcie_probe(struct platform_device *pdev) +diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c +index e06e9f4fc50f7..769eedeb8802a 100644 +--- a/drivers/pci/controller/vmd.c ++++ b/drivers/pci/controller/vmd.c +@@ -719,6 +719,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features) + resource_size_t offset[2] = {0}; + resource_size_t membar2_offset = 0x2000; + struct pci_bus *child; ++ struct pci_dev *dev; + int ret; + + /* +@@ -859,8 +860,25 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features) + + pci_scan_child_bus(vmd->bus); + vmd_domain_reset(vmd); +- list_for_each_entry(child, &vmd->bus->children, node) +- pci_reset_bus(child->self); ++ ++ /* When Intel VMD is enabled, the OS does not discover the Root Ports ++ * owned by Intel VMD within the MMCFG space. pci_reset_bus() applies ++ * a reset to the parent of the PCI device supplied as argument. This ++ * is why we pass a child device, so the reset can be triggered at ++ * the Intel bridge level and propagated to all the children in the ++ * hierarchy. ++ */ ++ list_for_each_entry(child, &vmd->bus->children, node) { ++ if (!list_empty(&child->devices)) { ++ dev = list_first_entry(&child->devices, ++ struct pci_dev, bus_list); ++ if (pci_reset_bus(dev)) ++ pci_warn(dev, "can't reset device: %d\n", ret); ++ ++ break; ++ } ++ } ++ + pci_assign_unassigned_bus_resources(vmd->bus); + + /* +@@ -980,6 +998,11 @@ static int vmd_resume(struct device *dev) + struct vmd_dev *vmd = pci_get_drvdata(pdev); + int err, i; + ++ if (vmd->irq_domain) ++ vmd_set_msi_remapping(vmd, true); ++ else ++ vmd_set_msi_remapping(vmd, false); ++ + for (i = 0; i < vmd->msix_count; i++) { + err = devm_request_irq(dev, vmd->irqs[i].virq, + vmd_irq, IRQF_NO_THREAD, +diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c +index 36b1801a061b7..55283d2379a6a 100644 +--- a/drivers/pci/endpoint/functions/pci-epf-test.c ++++ b/drivers/pci/endpoint/functions/pci-epf-test.c +@@ -979,7 +979,7 @@ static int pci_epf_test_bind(struct pci_epf *epf) + if (ret) + epf_test->dma_supported = false; + +- if (linkup_notifier) { ++ if (linkup_notifier || core_init_notifier) { + epf->nb.notifier_call = pci_epf_test_notifier; + pci_epc_register_notifier(epc, &epf->nb); + } else { +diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c +index 0ea85e1d292ec..fba0179939b8f 100644 +--- a/drivers/pci/endpoint/functions/pci-epf-vntb.c ++++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c +@@ -557,7 +557,7 @@ static int epf_ntb_db_bar_init(struct epf_ntb *ntb) + return ret; + + err_alloc_peer_mem: +- pci_epc_mem_free_addr(ntb->epf->epc, epf_bar->phys_addr, mw_addr, epf_bar->size); ++ pci_epf_free_space(ntb->epf, mw_addr, barno, 0); + return -1; + } + +diff --git a/drivers/pci/irq.c b/drivers/pci/irq.c +index 12ecd0aaa28d6..0050e8f6814ed 100644 +--- a/drivers/pci/irq.c ++++ b/drivers/pci/irq.c +@@ -44,6 +44,8 @@ int pci_request_irq(struct pci_dev *dev, unsigned int nr, irq_handler_t handler, + va_start(ap, fmt); + devname = kvasprintf(GFP_KERNEL, fmt, ap); + va_end(ap); ++ if (!devname) ++ return -ENOMEM; + + ret = request_threaded_irq(pci_irq_vector(dev, nr), handler, thread_fn, + irqflags, devname, dev_id); +diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c +index b66fa42c4b1fa..1d6f7b502020d 100644 +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -1891,9 +1891,6 @@ int pci_setup_device(struct pci_dev *dev) + + dev->broken_intx_masking = pci_intx_mask_broken(dev); + +- /* Clear errors left from system firmware */ +- pci_write_config_word(dev, PCI_STATUS, 0xffff); +- + switch (dev->hdr_type) { /* header type */ + case PCI_HEADER_TYPE_NORMAL: /* standard header */ + if (class == PCI_CLASS_BRIDGE_PCI) +diff --git a/drivers/perf/arm_dmc620_pmu.c b/drivers/perf/arm_dmc620_pmu.c +index 280a6ae3e27cf..54aa4658fb36e 100644 +--- a/drivers/perf/arm_dmc620_pmu.c ++++ b/drivers/perf/arm_dmc620_pmu.c +@@ -725,6 +725,8 @@ static struct platform_driver dmc620_pmu_driver = { + + static int __init dmc620_pmu_init(void) + { ++ int ret; ++ + cpuhp_state_num = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, + DMC620_DRVNAME, + NULL, +@@ -732,7 +734,11 @@ static int __init dmc620_pmu_init(void) + if (cpuhp_state_num < 0) + return cpuhp_state_num; + +- return platform_driver_register(&dmc620_pmu_driver); ++ ret = platform_driver_register(&dmc620_pmu_driver); ++ if (ret) ++ cpuhp_remove_multi_state(cpuhp_state_num); ++ ++ return ret; + } + + static void __exit dmc620_pmu_exit(void) +diff --git a/drivers/perf/arm_dsu_pmu.c b/drivers/perf/arm_dsu_pmu.c +index 4a15c86f45efb..fe2abb412c004 100644 +--- a/drivers/perf/arm_dsu_pmu.c ++++ b/drivers/perf/arm_dsu_pmu.c +@@ -858,7 +858,11 @@ static int __init dsu_pmu_init(void) + if (ret < 0) + return ret; + dsu_pmu_cpuhp_state = ret; +- return platform_driver_register(&dsu_pmu_driver); ++ ret = platform_driver_register(&dsu_pmu_driver); ++ if (ret) ++ cpuhp_remove_multi_state(dsu_pmu_cpuhp_state); ++ ++ return ret; + } + + static void __exit dsu_pmu_exit(void) +diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c +index 00d4c45a8017d..25a269d431e45 100644 +--- a/drivers/perf/arm_smmuv3_pmu.c ++++ b/drivers/perf/arm_smmuv3_pmu.c +@@ -959,6 +959,8 @@ static struct platform_driver smmu_pmu_driver = { + + static int __init arm_smmu_pmu_init(void) + { ++ int ret; ++ + cpuhp_state_num = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, + "perf/arm/pmcg:online", + NULL, +@@ -966,7 +968,11 @@ static int __init arm_smmu_pmu_init(void) + if (cpuhp_state_num < 0) + return cpuhp_state_num; + +- return platform_driver_register(&smmu_pmu_driver); ++ ret = platform_driver_register(&smmu_pmu_driver); ++ if (ret) ++ cpuhp_remove_multi_state(cpuhp_state_num); ++ ++ return ret; + } + module_init(arm_smmu_pmu_init); + +diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c +index 21771708597db..071e63d9a9ac6 100644 +--- a/drivers/perf/hisilicon/hisi_pcie_pmu.c ++++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c +@@ -693,10 +693,10 @@ static struct attribute *hisi_pcie_pmu_events_attr[] = { + HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_cnt, 0x10210), + HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_latency, 0x0011), + HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_cnt, 0x10011), +- HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_flux, 0x1005), +- HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_time, 0x11005), +- HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_flux, 0x2004), +- HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_time, 0x12004), ++ HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_flux, 0x0804), ++ HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_time, 0x10804), ++ HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_flux, 0x0405), ++ HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_time, 0x10405), + NULL + }; + +diff --git a/drivers/perf/marvell_cn10k_tad_pmu.c b/drivers/perf/marvell_cn10k_tad_pmu.c +index 69c3050a4348b..a1166afb37024 100644 +--- a/drivers/perf/marvell_cn10k_tad_pmu.c ++++ b/drivers/perf/marvell_cn10k_tad_pmu.c +@@ -408,7 +408,11 @@ static int __init tad_pmu_init(void) + if (ret < 0) + return ret; + tad_pmu_cpuhp_state = ret; +- return platform_driver_register(&tad_pmu_driver); ++ ret = platform_driver_register(&tad_pmu_driver); ++ if (ret) ++ cpuhp_remove_multi_state(tad_pmu_cpuhp_state); ++ ++ return ret; + } + + static void __exit tad_pmu_exit(void) +diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c +index 3a3831f6059a3..5472db9e87ef8 100644 +--- a/drivers/phy/allwinner/phy-sun4i-usb.c ++++ b/drivers/phy/allwinner/phy-sun4i-usb.c +@@ -120,6 +120,7 @@ struct sun4i_usb_phy_cfg { + u8 phyctl_offset; + bool dedicated_clocks; + bool phy0_dual_route; ++ bool needs_phy2_siddq; + int missing_phys; + }; + +@@ -289,6 +290,50 @@ static int sun4i_usb_phy_init(struct phy *_phy) + return ret; + } + ++ /* Some PHYs on some SoCs need the help of PHY2 to work. */ ++ if (data->cfg->needs_phy2_siddq && phy->index != 2) { ++ struct sun4i_usb_phy *phy2 = &data->phys[2]; ++ ++ ret = clk_prepare_enable(phy2->clk); ++ if (ret) { ++ reset_control_assert(phy->reset); ++ clk_disable_unprepare(phy->clk2); ++ clk_disable_unprepare(phy->clk); ++ return ret; ++ } ++ ++ ret = reset_control_deassert(phy2->reset); ++ if (ret) { ++ clk_disable_unprepare(phy2->clk); ++ reset_control_assert(phy->reset); ++ clk_disable_unprepare(phy->clk2); ++ clk_disable_unprepare(phy->clk); ++ return ret; ++ } ++ ++ /* ++ * This extra clock is just needed to access the ++ * REG_HCI_PHY_CTL PMU register for PHY2. ++ */ ++ ret = clk_prepare_enable(phy2->clk2); ++ if (ret) { ++ reset_control_assert(phy2->reset); ++ clk_disable_unprepare(phy2->clk); ++ reset_control_assert(phy->reset); ++ clk_disable_unprepare(phy->clk2); ++ clk_disable_unprepare(phy->clk); ++ return ret; ++ } ++ ++ if (phy2->pmu && data->cfg->hci_phy_ctl_clear) { ++ val = readl(phy2->pmu + REG_HCI_PHY_CTL); ++ val &= ~data->cfg->hci_phy_ctl_clear; ++ writel(val, phy2->pmu + REG_HCI_PHY_CTL); ++ } ++ ++ clk_disable_unprepare(phy->clk2); ++ } ++ + if (phy->pmu && data->cfg->hci_phy_ctl_clear) { + val = readl(phy->pmu + REG_HCI_PHY_CTL); + val &= ~data->cfg->hci_phy_ctl_clear; +@@ -354,6 +399,13 @@ static int sun4i_usb_phy_exit(struct phy *_phy) + data->phy0_init = false; + } + ++ if (data->cfg->needs_phy2_siddq && phy->index != 2) { ++ struct sun4i_usb_phy *phy2 = &data->phys[2]; ++ ++ clk_disable_unprepare(phy2->clk); ++ reset_control_assert(phy2->reset); ++ } ++ + sun4i_usb_phy_passby(phy, 0); + reset_control_assert(phy->reset); + clk_disable_unprepare(phy->clk2); +@@ -785,6 +837,13 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) + dev_err(dev, "failed to get clock %s\n", name); + return PTR_ERR(phy->clk2); + } ++ } else { ++ snprintf(name, sizeof(name), "pmu%d_clk", i); ++ phy->clk2 = devm_clk_get_optional(dev, name); ++ if (IS_ERR(phy->clk2)) { ++ dev_err(dev, "failed to get clock %s\n", name); ++ return PTR_ERR(phy->clk2); ++ } + } + + snprintf(name, sizeof(name), "usb%d_reset", i); +@@ -973,6 +1032,17 @@ static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = { + .missing_phys = BIT(1) | BIT(2), + }; + ++static const struct sun4i_usb_phy_cfg sun50i_h616_cfg = { ++ .num_phys = 4, ++ .type = sun50i_h6_phy, ++ .disc_thresh = 3, ++ .phyctl_offset = REG_PHYCTL_A33, ++ .dedicated_clocks = true, ++ .phy0_dual_route = true, ++ .hci_phy_ctl_clear = PHY_CTL_SIDDQ, ++ .needs_phy2_siddq = true, ++}; ++ + static const struct of_device_id sun4i_usb_phy_of_match[] = { + { .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg }, + { .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg }, +@@ -988,6 +1058,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = { + { .compatible = "allwinner,sun50i-a64-usb-phy", + .data = &sun50i_a64_cfg}, + { .compatible = "allwinner,sun50i-h6-usb-phy", .data = &sun50i_h6_cfg }, ++ { .compatible = "allwinner,sun50i-h616-usb-phy", .data = &sun50i_h616_cfg }, + { }, + }; + MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match); +diff --git a/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c b/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c +index d2524b70ea161..3b374b37b965b 100644 +--- a/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c ++++ b/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c +@@ -331,13 +331,12 @@ static void usb_uninit_common_7216(struct brcm_usb_init_params *params) + + pr_debug("%s\n", __func__); + +- if (!params->wake_enabled) { +- USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN); +- ++ if (params->wake_enabled) { + /* Switch to using slower clock during suspend to save power */ + USB_CTRL_SET(ctrl, USB_PM, XHC_S2_CLK_SWITCH_EN); +- } else { + usb_wake_enable_7216(params, true); ++ } else { ++ USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN); + } + } + +@@ -425,7 +424,6 @@ void brcm_usb_dvr_init_7216(struct brcm_usb_init_params *params) + + params->family_name = "7216"; + params->ops = &bcm7216_ops; +- params->suspend_with_clocks = true; + } + + void brcm_usb_dvr_init_7211b0(struct brcm_usb_init_params *params) +@@ -435,5 +433,4 @@ void brcm_usb_dvr_init_7211b0(struct brcm_usb_init_params *params) + + params->family_name = "7211"; + params->ops = &bcm7211b0_ops; +- params->suspend_with_clocks = true; + } +diff --git a/drivers/phy/broadcom/phy-brcm-usb-init.h b/drivers/phy/broadcom/phy-brcm-usb-init.h +index 1ccb5ddab865c..3236e94988428 100644 +--- a/drivers/phy/broadcom/phy-brcm-usb-init.h ++++ b/drivers/phy/broadcom/phy-brcm-usb-init.h +@@ -61,7 +61,6 @@ struct brcm_usb_init_params { + const struct brcm_usb_init_ops *ops; + struct regmap *syscon_piarbctl; + bool wake_enabled; +- bool suspend_with_clocks; + }; + + void brcm_usb_dvr_init_4908(struct brcm_usb_init_params *params); +diff --git a/drivers/phy/broadcom/phy-brcm-usb.c b/drivers/phy/broadcom/phy-brcm-usb.c +index 2cb3779fcdf82..2bfd78e2d8fd6 100644 +--- a/drivers/phy/broadcom/phy-brcm-usb.c ++++ b/drivers/phy/broadcom/phy-brcm-usb.c +@@ -102,9 +102,9 @@ static int brcm_pm_notifier(struct notifier_block *notifier, + + static irqreturn_t brcm_usb_phy_wake_isr(int irq, void *dev_id) + { +- struct phy *gphy = dev_id; ++ struct device *dev = dev_id; + +- pm_wakeup_event(&gphy->dev, 0); ++ pm_wakeup_event(dev, 0); + + return IRQ_HANDLED; + } +@@ -451,7 +451,7 @@ static int brcm_usb_phy_dvr_init(struct platform_device *pdev, + if (priv->wake_irq >= 0) { + err = devm_request_irq(dev, priv->wake_irq, + brcm_usb_phy_wake_isr, 0, +- dev_name(dev), gphy); ++ dev_name(dev), dev); + if (err < 0) + return err; + device_set_wakeup_capable(dev, 1); +@@ -598,7 +598,7 @@ static int brcm_usb_phy_suspend(struct device *dev) + * and newer XHCI->2.0-clks/3.0-clks. + */ + +- if (!priv->ini.suspend_with_clocks) { ++ if (!priv->ini.wake_enabled) { + if (priv->phys[BRCM_USB_PHY_3_0].inited) + clk_disable_unprepare(priv->usb_30_clk); + if (priv->phys[BRCM_USB_PHY_2_0].inited || +@@ -615,8 +615,10 @@ static int brcm_usb_phy_resume(struct device *dev) + { + struct brcm_usb_phy_data *priv = dev_get_drvdata(dev); + +- clk_prepare_enable(priv->usb_20_clk); +- clk_prepare_enable(priv->usb_30_clk); ++ if (!priv->ini.wake_enabled) { ++ clk_prepare_enable(priv->usb_20_clk); ++ clk_prepare_enable(priv->usb_30_clk); ++ } + brcm_usb_init_ipp(&priv->ini); + + /* +diff --git a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c +index 67712c77d806f..d641b345afa35 100644 +--- a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c ++++ b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c +@@ -826,6 +826,9 @@ mvebu_a3700_comphy_usb3_power_on(struct mvebu_a3700_comphy_lane *lane) + if (ret) + return ret; + ++ /* COMPHY register reset (cleared automatically) */ ++ comphy_lane_reg_set(lane, COMPHY_SFT_RESET, SFT_RST, SFT_RST); ++ + /* + * 0. Set PHY OTG Control(0x5d034), bit 4, Power up OTG module The + * register belong to UTMI module, so it is set in UTMI phy driver. +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +index 5be5348fbb26b..bb40172e23d49 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +@@ -14,6 +14,7 @@ + #include <linux/of.h> + #include <linux/of_device.h> + #include <linux/of_address.h> ++#include <linux/phy/pcie.h> + #include <linux/phy/phy.h> + #include <linux/platform_device.h> + #include <linux/regulator/consumer.h> +@@ -505,6 +506,13 @@ static const struct qmp_phy_init_tbl ipq8074_pcie_gen3_pcs_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V4_PCS_FLL_CNTRL1, 0x01), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_H, 0x0), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x1), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_G12S1_TXDEEMPH_M3P5DB, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_DCC_CAL_CONFIG, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_gen3_pcs_misc_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS, 0x0), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_H, 0x00), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), +@@ -517,11 +525,7 @@ static const struct qmp_phy_init_tbl ipq8074_pcie_gen3_pcs_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_MODE2_CONFIG2, 0x50), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_MODE2_CONFIG4, 0x1a), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_MODE2_CONFIG5, 0x6), +- QMP_PHY_INIT_CFG(QPHY_V4_PCS_G12S1_TXDEEMPH_M3P5DB, 0x10), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), +- QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_DCC_CAL_CONFIG, 0x01), +- QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), +- QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d), + }; + + static const struct qmp_phy_init_tbl sdm845_qmp_pcie_serdes_tbl[] = { +@@ -1184,15 +1188,29 @@ static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_pcs_misc_tbl[] = { + }; + + static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x46), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_CFG, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_MISC1, 0x88), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_MODE, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_DC_LEVEL_CTRL, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_rc_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER1, 0x31), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER2, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE0, 0xde), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE0, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE1, 0x97), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE1, 0x0c), +- QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_ENABLE1, 0x90), +- QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16), +@@ -1200,8 +1218,6 @@ static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x08), +- QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x46), +- QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_CFG, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x14), +@@ -1214,17 +1230,8 @@ static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE1, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE1, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE1, 0x05), +- QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_SELECT, 0x34), +- QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x12), +- QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00), +- QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE0, 0x0a), +- QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE1, 0x04), +- QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_MISC1, 0x88), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORE_CLK_EN, 0x20), +- QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_CONFIG, 0x06), +- QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_MODE, 0x14), +- QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_DC_LEVEL_CTRL, 0x0f), + }; + + static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_tx_tbl[] = { +@@ -1285,46 +1292,80 @@ static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_rx_tbl[] = { + }; + + static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_pcs_tbl[] = { +- QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG2, 0x16), +- QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG3, 0x22), +- QMP_PHY_INIT_CFG(QPHY_V5_PCS_G3S2_PRE_GAIN, 0x2e), +- QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0x99), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_EQ_CONFIG4, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_EQ_CONFIG5, 0x22), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_G3S2_PRE_GAIN, 0x2e), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_RX_SIGDET_LVL, 0x99), + }; + + static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_pcs_misc_tbl[] = { +- QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), +- QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), + QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_G4_EQ_CONFIG5, 0x02), + QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_EQ_CONFIG1, 0x16), + QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_RX_MARGINING_CONFIG3, 0x28), + QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_G4_PRE_GAIN, 0x2e), + }; + ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_rc_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_PRESET_P10_POST, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_ep_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BG_TIMER, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYS_CLK_CTRL, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x27), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_INTEGLOOP_GAIN0_MODE0, 0xfb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_INTEGLOOP_GAIN1_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_INTEGLOOP_GAIN0_MODE1, 0xfb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_INTEGLOOP_GAIN1_MODE1, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORE_CLK_EN, 0x60), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_ep_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_OSC_DTCT_MODE2_CONFIG5, 0x08), ++}; ++ ++struct qmp_phy_cfg_tables { ++ const struct qmp_phy_init_tbl *serdes; ++ int serdes_num; ++ const struct qmp_phy_init_tbl *tx; ++ int tx_num; ++ const struct qmp_phy_init_tbl *rx; ++ int rx_num; ++ const struct qmp_phy_init_tbl *pcs; ++ int pcs_num; ++ const struct qmp_phy_init_tbl *pcs_misc; ++ int pcs_misc_num; ++}; ++ + /* struct qmp_phy_cfg - per-PHY initialization config */ + struct qmp_phy_cfg { + int lanes; + +- /* Init sequence for PHY blocks - serdes, tx, rx, pcs */ +- const struct qmp_phy_init_tbl *serdes_tbl; +- int serdes_tbl_num; +- const struct qmp_phy_init_tbl *serdes_tbl_sec; +- int serdes_tbl_num_sec; +- const struct qmp_phy_init_tbl *tx_tbl; +- int tx_tbl_num; +- const struct qmp_phy_init_tbl *tx_tbl_sec; +- int tx_tbl_num_sec; +- const struct qmp_phy_init_tbl *rx_tbl; +- int rx_tbl_num; +- const struct qmp_phy_init_tbl *rx_tbl_sec; +- int rx_tbl_num_sec; +- const struct qmp_phy_init_tbl *pcs_tbl; +- int pcs_tbl_num; +- const struct qmp_phy_init_tbl *pcs_tbl_sec; +- int pcs_tbl_num_sec; +- const struct qmp_phy_init_tbl *pcs_misc_tbl; +- int pcs_misc_tbl_num; +- const struct qmp_phy_init_tbl *pcs_misc_tbl_sec; +- int pcs_misc_tbl_num_sec; ++ /* Main init sequence for PHY blocks - serdes, tx, rx, pcs */ ++ const struct qmp_phy_cfg_tables tables; ++ /* ++ * Additional init sequences for PHY blocks, providing additional ++ * register programming. They are used for providing separate sequences ++ * for the Root Complex and End Point use cases. ++ * ++ * If EP mode is not supported, both tables can be left unset. ++ */ ++ const struct qmp_phy_cfg_tables *tables_rc; ++ const struct qmp_phy_cfg_tables *tables_ep; + + /* clock ids to be requested */ + const char * const *clk_list; +@@ -1344,11 +1385,7 @@ struct qmp_phy_cfg { + /* bit offset of PHYSTATUS in QPHY_PCS_STATUS register */ + unsigned int phy_status; + +- /* true, if PHY needs delay after POWER_DOWN */ +- bool has_pwrdn_delay; +- /* power_down delay in usec */ +- int pwrdn_delay_min; +- int pwrdn_delay_max; ++ bool skip_start_delay; + + /* QMP PHY pipe clock interface rate */ + unsigned long pipe_clock_rate; +@@ -1368,6 +1405,7 @@ struct qmp_phy_cfg { + * @pcs_misc: iomapped memory space for lane's pcs_misc + * @pipe_clk: pipe clock + * @qmp: QMP phy to which this lane belongs ++ * @mode: currently selected PHY mode + */ + struct qmp_phy { + struct phy *phy; +@@ -1381,6 +1419,7 @@ struct qmp_phy { + void __iomem *pcs_misc; + struct clk *pipe_clk; + struct qcom_qmp *qmp; ++ int mode; + }; + + /** +@@ -1459,14 +1498,16 @@ static const char * const sdm845_pciephy_reset_l[] = { + static const struct qmp_phy_cfg ipq8074_pciephy_cfg = { + .lanes = 1, + +- .serdes_tbl = ipq8074_pcie_serdes_tbl, +- .serdes_tbl_num = ARRAY_SIZE(ipq8074_pcie_serdes_tbl), +- .tx_tbl = ipq8074_pcie_tx_tbl, +- .tx_tbl_num = ARRAY_SIZE(ipq8074_pcie_tx_tbl), +- .rx_tbl = ipq8074_pcie_rx_tbl, +- .rx_tbl_num = ARRAY_SIZE(ipq8074_pcie_rx_tbl), +- .pcs_tbl = ipq8074_pcie_pcs_tbl, +- .pcs_tbl_num = ARRAY_SIZE(ipq8074_pcie_pcs_tbl), ++ .tables = { ++ .serdes = ipq8074_pcie_serdes_tbl, ++ .serdes_num = ARRAY_SIZE(ipq8074_pcie_serdes_tbl), ++ .tx = ipq8074_pcie_tx_tbl, ++ .tx_num = ARRAY_SIZE(ipq8074_pcie_tx_tbl), ++ .rx = ipq8074_pcie_rx_tbl, ++ .rx_num = ARRAY_SIZE(ipq8074_pcie_rx_tbl), ++ .pcs = ipq8074_pcie_pcs_tbl, ++ .pcs_num = ARRAY_SIZE(ipq8074_pcie_pcs_tbl), ++ }, + .clk_list = ipq8074_pciephy_clk_l, + .num_clks = ARRAY_SIZE(ipq8074_pciephy_clk_l), + .reset_list = ipq8074_pciephy_reset_l, +@@ -1478,23 +1519,23 @@ static const struct qmp_phy_cfg ipq8074_pciephy_cfg = { + .start_ctrl = SERDES_START | PCS_START, + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, +- +- .has_pwrdn_delay = true, +- .pwrdn_delay_min = 995, /* us */ +- .pwrdn_delay_max = 1005, /* us */ + }; + + static const struct qmp_phy_cfg ipq8074_pciephy_gen3_cfg = { + .lanes = 1, + +- .serdes_tbl = ipq8074_pcie_gen3_serdes_tbl, +- .serdes_tbl_num = ARRAY_SIZE(ipq8074_pcie_gen3_serdes_tbl), +- .tx_tbl = ipq8074_pcie_gen3_tx_tbl, +- .tx_tbl_num = ARRAY_SIZE(ipq8074_pcie_gen3_tx_tbl), +- .rx_tbl = ipq8074_pcie_gen3_rx_tbl, +- .rx_tbl_num = ARRAY_SIZE(ipq8074_pcie_gen3_rx_tbl), +- .pcs_tbl = ipq8074_pcie_gen3_pcs_tbl, +- .pcs_tbl_num = ARRAY_SIZE(ipq8074_pcie_gen3_pcs_tbl), ++ .tables = { ++ .serdes = ipq8074_pcie_gen3_serdes_tbl, ++ .serdes_num = ARRAY_SIZE(ipq8074_pcie_gen3_serdes_tbl), ++ .tx = ipq8074_pcie_gen3_tx_tbl, ++ .tx_num = ARRAY_SIZE(ipq8074_pcie_gen3_tx_tbl), ++ .rx = ipq8074_pcie_gen3_rx_tbl, ++ .rx_num = ARRAY_SIZE(ipq8074_pcie_gen3_rx_tbl), ++ .pcs = ipq8074_pcie_gen3_pcs_tbl, ++ .pcs_num = ARRAY_SIZE(ipq8074_pcie_gen3_pcs_tbl), ++ .pcs_misc = ipq8074_pcie_gen3_pcs_misc_tbl, ++ .pcs_misc_num = ARRAY_SIZE(ipq8074_pcie_gen3_pcs_misc_tbl), ++ }, + .clk_list = ipq8074_pciephy_clk_l, + .num_clks = ARRAY_SIZE(ipq8074_pciephy_clk_l), + .reset_list = ipq8074_pciephy_reset_l, +@@ -1505,10 +1546,7 @@ static const struct qmp_phy_cfg ipq8074_pciephy_gen3_cfg = { + + .start_ctrl = SERDES_START | PCS_START, + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, +- +- .has_pwrdn_delay = true, +- .pwrdn_delay_min = 995, /* us */ +- .pwrdn_delay_max = 1005, /* us */ ++ .phy_status = PHYSTATUS, + + .pipe_clock_rate = 250000000, + }; +@@ -1516,16 +1554,18 @@ static const struct qmp_phy_cfg ipq8074_pciephy_gen3_cfg = { + static const struct qmp_phy_cfg ipq6018_pciephy_cfg = { + .lanes = 1, + +- .serdes_tbl = ipq6018_pcie_serdes_tbl, +- .serdes_tbl_num = ARRAY_SIZE(ipq6018_pcie_serdes_tbl), +- .tx_tbl = ipq6018_pcie_tx_tbl, +- .tx_tbl_num = ARRAY_SIZE(ipq6018_pcie_tx_tbl), +- .rx_tbl = ipq6018_pcie_rx_tbl, +- .rx_tbl_num = ARRAY_SIZE(ipq6018_pcie_rx_tbl), +- .pcs_tbl = ipq6018_pcie_pcs_tbl, +- .pcs_tbl_num = ARRAY_SIZE(ipq6018_pcie_pcs_tbl), +- .pcs_misc_tbl = ipq6018_pcie_pcs_misc_tbl, +- .pcs_misc_tbl_num = ARRAY_SIZE(ipq6018_pcie_pcs_misc_tbl), ++ .tables = { ++ .serdes = ipq6018_pcie_serdes_tbl, ++ .serdes_num = ARRAY_SIZE(ipq6018_pcie_serdes_tbl), ++ .tx = ipq6018_pcie_tx_tbl, ++ .tx_num = ARRAY_SIZE(ipq6018_pcie_tx_tbl), ++ .rx = ipq6018_pcie_rx_tbl, ++ .rx_num = ARRAY_SIZE(ipq6018_pcie_rx_tbl), ++ .pcs = ipq6018_pcie_pcs_tbl, ++ .pcs_num = ARRAY_SIZE(ipq6018_pcie_pcs_tbl), ++ .pcs_misc = ipq6018_pcie_pcs_misc_tbl, ++ .pcs_misc_num = ARRAY_SIZE(ipq6018_pcie_pcs_misc_tbl), ++ }, + .clk_list = ipq8074_pciephy_clk_l, + .num_clks = ARRAY_SIZE(ipq8074_pciephy_clk_l), + .reset_list = ipq8074_pciephy_reset_l, +@@ -1536,25 +1576,24 @@ static const struct qmp_phy_cfg ipq6018_pciephy_cfg = { + + .start_ctrl = SERDES_START | PCS_START, + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, +- +- .has_pwrdn_delay = true, +- .pwrdn_delay_min = 995, /* us */ +- .pwrdn_delay_max = 1005, /* us */ ++ .phy_status = PHYSTATUS, + }; + + static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = { + .lanes = 1, + +- .serdes_tbl = sdm845_qmp_pcie_serdes_tbl, +- .serdes_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_serdes_tbl), +- .tx_tbl = sdm845_qmp_pcie_tx_tbl, +- .tx_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_tx_tbl), +- .rx_tbl = sdm845_qmp_pcie_rx_tbl, +- .rx_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_rx_tbl), +- .pcs_tbl = sdm845_qmp_pcie_pcs_tbl, +- .pcs_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_pcs_tbl), +- .pcs_misc_tbl = sdm845_qmp_pcie_pcs_misc_tbl, +- .pcs_misc_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_pcs_misc_tbl), ++ .tables = { ++ .serdes = sdm845_qmp_pcie_serdes_tbl, ++ .serdes_num = ARRAY_SIZE(sdm845_qmp_pcie_serdes_tbl), ++ .tx = sdm845_qmp_pcie_tx_tbl, ++ .tx_num = ARRAY_SIZE(sdm845_qmp_pcie_tx_tbl), ++ .rx = sdm845_qmp_pcie_rx_tbl, ++ .rx_num = ARRAY_SIZE(sdm845_qmp_pcie_rx_tbl), ++ .pcs = sdm845_qmp_pcie_pcs_tbl, ++ .pcs_num = ARRAY_SIZE(sdm845_qmp_pcie_pcs_tbl), ++ .pcs_misc = sdm845_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_num = ARRAY_SIZE(sdm845_qmp_pcie_pcs_misc_tbl), ++ }, + .clk_list = sdm845_pciephy_clk_l, + .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), + .reset_list = sdm845_pciephy_reset_l, +@@ -1566,23 +1605,21 @@ static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = { + .start_ctrl = PCS_START | SERDES_START, + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, +- +- .has_pwrdn_delay = true, +- .pwrdn_delay_min = 995, /* us */ +- .pwrdn_delay_max = 1005, /* us */ + }; + + static const struct qmp_phy_cfg sdm845_qhp_pciephy_cfg = { + .lanes = 1, + +- .serdes_tbl = sdm845_qhp_pcie_serdes_tbl, +- .serdes_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_serdes_tbl), +- .tx_tbl = sdm845_qhp_pcie_tx_tbl, +- .tx_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_tx_tbl), +- .rx_tbl = sdm845_qhp_pcie_rx_tbl, +- .rx_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_rx_tbl), +- .pcs_tbl = sdm845_qhp_pcie_pcs_tbl, +- .pcs_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_pcs_tbl), ++ .tables = { ++ .serdes = sdm845_qhp_pcie_serdes_tbl, ++ .serdes_num = ARRAY_SIZE(sdm845_qhp_pcie_serdes_tbl), ++ .tx = sdm845_qhp_pcie_tx_tbl, ++ .tx_num = ARRAY_SIZE(sdm845_qhp_pcie_tx_tbl), ++ .rx = sdm845_qhp_pcie_rx_tbl, ++ .rx_num = ARRAY_SIZE(sdm845_qhp_pcie_rx_tbl), ++ .pcs = sdm845_qhp_pcie_pcs_tbl, ++ .pcs_num = ARRAY_SIZE(sdm845_qhp_pcie_pcs_tbl), ++ }, + .clk_list = sdm845_pciephy_clk_l, + .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), + .reset_list = sdm845_pciephy_reset_l, +@@ -1594,33 +1631,33 @@ static const struct qmp_phy_cfg sdm845_qhp_pciephy_cfg = { + .start_ctrl = PCS_START | SERDES_START, + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, +- +- .has_pwrdn_delay = true, +- .pwrdn_delay_min = 995, /* us */ +- .pwrdn_delay_max = 1005, /* us */ + }; + + static const struct qmp_phy_cfg sm8250_qmp_gen3x1_pciephy_cfg = { + .lanes = 1, + +- .serdes_tbl = sm8250_qmp_pcie_serdes_tbl, +- .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), +- .serdes_tbl_sec = sm8250_qmp_gen3x1_pcie_serdes_tbl, +- .serdes_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_serdes_tbl), +- .tx_tbl = sm8250_qmp_pcie_tx_tbl, +- .tx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_tx_tbl), +- .rx_tbl = sm8250_qmp_pcie_rx_tbl, +- .rx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_rx_tbl), +- .rx_tbl_sec = sm8250_qmp_gen3x1_pcie_rx_tbl, +- .rx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_rx_tbl), +- .pcs_tbl = sm8250_qmp_pcie_pcs_tbl, +- .pcs_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_tbl), +- .pcs_tbl_sec = sm8250_qmp_gen3x1_pcie_pcs_tbl, +- .pcs_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_pcs_tbl), +- .pcs_misc_tbl = sm8250_qmp_pcie_pcs_misc_tbl, +- .pcs_misc_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_misc_tbl), +- .pcs_misc_tbl_sec = sm8250_qmp_gen3x1_pcie_pcs_misc_tbl, +- .pcs_misc_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_pcs_misc_tbl), ++ .tables = { ++ .serdes = sm8250_qmp_pcie_serdes_tbl, ++ .serdes_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), ++ .tx = sm8250_qmp_pcie_tx_tbl, ++ .tx_num = ARRAY_SIZE(sm8250_qmp_pcie_tx_tbl), ++ .rx = sm8250_qmp_pcie_rx_tbl, ++ .rx_num = ARRAY_SIZE(sm8250_qmp_pcie_rx_tbl), ++ .pcs = sm8250_qmp_pcie_pcs_tbl, ++ .pcs_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_tbl), ++ .pcs_misc = sm8250_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_misc_tbl), ++ }, ++ .tables_rc = &(const struct qmp_phy_cfg_tables) { ++ .serdes = sm8250_qmp_gen3x1_pcie_serdes_tbl, ++ .serdes_num = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_serdes_tbl), ++ .rx = sm8250_qmp_gen3x1_pcie_rx_tbl, ++ .rx_num = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_rx_tbl), ++ .pcs = sm8250_qmp_gen3x1_pcie_pcs_tbl, ++ .pcs_num = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_pcs_tbl), ++ .pcs_misc = sm8250_qmp_gen3x1_pcie_pcs_misc_tbl, ++ .pcs_misc_num = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_pcs_misc_tbl), ++ }, + .clk_list = sdm845_pciephy_clk_l, + .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), + .reset_list = sdm845_pciephy_reset_l, +@@ -1632,33 +1669,33 @@ static const struct qmp_phy_cfg sm8250_qmp_gen3x1_pciephy_cfg = { + .start_ctrl = PCS_START | SERDES_START, + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, +- +- .has_pwrdn_delay = true, +- .pwrdn_delay_min = 995, /* us */ +- .pwrdn_delay_max = 1005, /* us */ + }; + + static const struct qmp_phy_cfg sm8250_qmp_gen3x2_pciephy_cfg = { + .lanes = 2, + +- .serdes_tbl = sm8250_qmp_pcie_serdes_tbl, +- .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), +- .tx_tbl = sm8250_qmp_pcie_tx_tbl, +- .tx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_tx_tbl), +- .tx_tbl_sec = sm8250_qmp_gen3x2_pcie_tx_tbl, +- .tx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_tx_tbl), +- .rx_tbl = sm8250_qmp_pcie_rx_tbl, +- .rx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_rx_tbl), +- .rx_tbl_sec = sm8250_qmp_gen3x2_pcie_rx_tbl, +- .rx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_rx_tbl), +- .pcs_tbl = sm8250_qmp_pcie_pcs_tbl, +- .pcs_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_tbl), +- .pcs_tbl_sec = sm8250_qmp_gen3x2_pcie_pcs_tbl, +- .pcs_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_pcs_tbl), +- .pcs_misc_tbl = sm8250_qmp_pcie_pcs_misc_tbl, +- .pcs_misc_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_misc_tbl), +- .pcs_misc_tbl_sec = sm8250_qmp_gen3x2_pcie_pcs_misc_tbl, +- .pcs_misc_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_pcs_misc_tbl), ++ .tables = { ++ .serdes = sm8250_qmp_pcie_serdes_tbl, ++ .serdes_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), ++ .tx = sm8250_qmp_pcie_tx_tbl, ++ .tx_num = ARRAY_SIZE(sm8250_qmp_pcie_tx_tbl), ++ .rx = sm8250_qmp_pcie_rx_tbl, ++ .rx_num = ARRAY_SIZE(sm8250_qmp_pcie_rx_tbl), ++ .pcs = sm8250_qmp_pcie_pcs_tbl, ++ .pcs_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_tbl), ++ .pcs_misc = sm8250_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_misc_tbl), ++ }, ++ .tables_rc = &(const struct qmp_phy_cfg_tables) { ++ .tx = sm8250_qmp_gen3x2_pcie_tx_tbl, ++ .tx_num = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_tx_tbl), ++ .rx = sm8250_qmp_gen3x2_pcie_rx_tbl, ++ .rx_num = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_rx_tbl), ++ .pcs = sm8250_qmp_gen3x2_pcie_pcs_tbl, ++ .pcs_num = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_pcs_tbl), ++ .pcs_misc = sm8250_qmp_gen3x2_pcie_pcs_misc_tbl, ++ .pcs_misc_num = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_pcs_misc_tbl), ++ }, + .clk_list = sdm845_pciephy_clk_l, + .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), + .reset_list = sdm845_pciephy_reset_l, +@@ -1670,23 +1707,21 @@ static const struct qmp_phy_cfg sm8250_qmp_gen3x2_pciephy_cfg = { + .start_ctrl = PCS_START | SERDES_START, + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, +- +- .has_pwrdn_delay = true, +- .pwrdn_delay_min = 995, /* us */ +- .pwrdn_delay_max = 1005, /* us */ + }; + + static const struct qmp_phy_cfg msm8998_pciephy_cfg = { + .lanes = 1, + +- .serdes_tbl = msm8998_pcie_serdes_tbl, +- .serdes_tbl_num = ARRAY_SIZE(msm8998_pcie_serdes_tbl), +- .tx_tbl = msm8998_pcie_tx_tbl, +- .tx_tbl_num = ARRAY_SIZE(msm8998_pcie_tx_tbl), +- .rx_tbl = msm8998_pcie_rx_tbl, +- .rx_tbl_num = ARRAY_SIZE(msm8998_pcie_rx_tbl), +- .pcs_tbl = msm8998_pcie_pcs_tbl, +- .pcs_tbl_num = ARRAY_SIZE(msm8998_pcie_pcs_tbl), ++ .tables = { ++ .serdes = msm8998_pcie_serdes_tbl, ++ .serdes_num = ARRAY_SIZE(msm8998_pcie_serdes_tbl), ++ .tx = msm8998_pcie_tx_tbl, ++ .tx_num = ARRAY_SIZE(msm8998_pcie_tx_tbl), ++ .rx = msm8998_pcie_rx_tbl, ++ .rx_num = ARRAY_SIZE(msm8998_pcie_rx_tbl), ++ .pcs = msm8998_pcie_pcs_tbl, ++ .pcs_num = ARRAY_SIZE(msm8998_pcie_pcs_tbl), ++ }, + .clk_list = msm8996_phy_clk_l, + .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), + .reset_list = ipq8074_pciephy_reset_l, +@@ -1698,21 +1733,25 @@ static const struct qmp_phy_cfg msm8998_pciephy_cfg = { + .start_ctrl = SERDES_START | PCS_START, + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, ++ ++ .skip_start_delay = true, + }; + + static const struct qmp_phy_cfg sc8180x_pciephy_cfg = { + .lanes = 1, + +- .serdes_tbl = sc8180x_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, +- .rx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_rx_tbl), +- .pcs_tbl = sc8180x_qmp_pcie_pcs_tbl, +- .pcs_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_tbl), +- .pcs_misc_tbl = sc8180x_qmp_pcie_pcs_misc_tbl, +- .pcs_misc_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_misc_tbl), ++ .tables = { ++ .serdes = sc8180x_qmp_pcie_serdes_tbl, ++ .serdes_num = ARRAY_SIZE(sc8180x_qmp_pcie_serdes_tbl), ++ .tx = sc8180x_qmp_pcie_tx_tbl, ++ .tx_num = ARRAY_SIZE(sc8180x_qmp_pcie_tx_tbl), ++ .rx = sc8180x_qmp_pcie_rx_tbl, ++ .rx_num = ARRAY_SIZE(sc8180x_qmp_pcie_rx_tbl), ++ .pcs = sc8180x_qmp_pcie_pcs_tbl, ++ .pcs_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_tbl), ++ .pcs_misc = sc8180x_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_misc_tbl), ++ }, + .clk_list = sdm845_pciephy_clk_l, + .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), + .reset_list = sdm845_pciephy_reset_l, +@@ -1723,25 +1762,24 @@ static const struct qmp_phy_cfg sc8180x_pciephy_cfg = { + + .start_ctrl = PCS_START | SERDES_START, + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, +- +- .has_pwrdn_delay = true, +- .pwrdn_delay_min = 995, /* us */ +- .pwrdn_delay_max = 1005, /* us */ ++ .phy_status = PHYSTATUS, + }; + + static const struct qmp_phy_cfg sdx55_qmp_pciephy_cfg = { + .lanes = 2, + +- .serdes_tbl = sdx55_qmp_pcie_serdes_tbl, +- .serdes_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_serdes_tbl), +- .tx_tbl = sdx55_qmp_pcie_tx_tbl, +- .tx_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_tx_tbl), +- .rx_tbl = sdx55_qmp_pcie_rx_tbl, +- .rx_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_rx_tbl), +- .pcs_tbl = sdx55_qmp_pcie_pcs_tbl, +- .pcs_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_pcs_tbl), +- .pcs_misc_tbl = sdx55_qmp_pcie_pcs_misc_tbl, +- .pcs_misc_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_pcs_misc_tbl), ++ .tables = { ++ .serdes = sdx55_qmp_pcie_serdes_tbl, ++ .serdes_num = ARRAY_SIZE(sdx55_qmp_pcie_serdes_tbl), ++ .tx = sdx55_qmp_pcie_tx_tbl, ++ .tx_num = ARRAY_SIZE(sdx55_qmp_pcie_tx_tbl), ++ .rx = sdx55_qmp_pcie_rx_tbl, ++ .rx_num = ARRAY_SIZE(sdx55_qmp_pcie_rx_tbl), ++ .pcs = sdx55_qmp_pcie_pcs_tbl, ++ .pcs_num = ARRAY_SIZE(sdx55_qmp_pcie_pcs_tbl), ++ .pcs_misc = sdx55_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_num = ARRAY_SIZE(sdx55_qmp_pcie_pcs_misc_tbl), ++ }, + .clk_list = sdm845_pciephy_clk_l, + .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), + .reset_list = sdm845_pciephy_reset_l, +@@ -1753,25 +1791,23 @@ static const struct qmp_phy_cfg sdx55_qmp_pciephy_cfg = { + .start_ctrl = PCS_START | SERDES_START, + .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS_4_20, +- +- .has_pwrdn_delay = true, +- .pwrdn_delay_min = 995, /* us */ +- .pwrdn_delay_max = 1005, /* us */ + }; + + static const struct qmp_phy_cfg sm8450_qmp_gen3x1_pciephy_cfg = { + .lanes = 1, + +- .serdes_tbl = sm8450_qmp_gen3x1_pcie_serdes_tbl, +- .serdes_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_serdes_tbl), +- .tx_tbl = sm8450_qmp_gen3x1_pcie_tx_tbl, +- .tx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_tx_tbl), +- .rx_tbl = sm8450_qmp_gen3x1_pcie_rx_tbl, +- .rx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_rx_tbl), +- .pcs_tbl = sm8450_qmp_gen3x1_pcie_pcs_tbl, +- .pcs_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_pcs_tbl), +- .pcs_misc_tbl = sm8450_qmp_gen3x1_pcie_pcs_misc_tbl, +- .pcs_misc_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_pcs_misc_tbl), ++ .tables = { ++ .serdes = sm8450_qmp_gen3x1_pcie_serdes_tbl, ++ .serdes_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_serdes_tbl), ++ .tx = sm8450_qmp_gen3x1_pcie_tx_tbl, ++ .tx_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_tx_tbl), ++ .rx = sm8450_qmp_gen3x1_pcie_rx_tbl, ++ .rx_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_rx_tbl), ++ .pcs = sm8450_qmp_gen3x1_pcie_pcs_tbl, ++ .pcs_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_pcs_tbl), ++ .pcs_misc = sm8450_qmp_gen3x1_pcie_pcs_misc_tbl, ++ .pcs_misc_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_pcs_misc_tbl), ++ }, + .clk_list = sdm845_pciephy_clk_l, + .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), + .reset_list = sdm845_pciephy_reset_l, +@@ -1783,25 +1819,38 @@ static const struct qmp_phy_cfg sm8450_qmp_gen3x1_pciephy_cfg = { + .start_ctrl = SERDES_START | PCS_START, + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, +- +- .has_pwrdn_delay = true, +- .pwrdn_delay_min = 995, /* us */ +- .pwrdn_delay_max = 1005, /* us */ + }; + + static const struct qmp_phy_cfg sm8450_qmp_gen4x2_pciephy_cfg = { + .lanes = 2, + +- .serdes_tbl = sm8450_qmp_gen4x2_pcie_serdes_tbl, +- .serdes_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_serdes_tbl), +- .tx_tbl = sm8450_qmp_gen4x2_pcie_tx_tbl, +- .tx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_tx_tbl), +- .rx_tbl = sm8450_qmp_gen4x2_pcie_rx_tbl, +- .rx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_rx_tbl), +- .pcs_tbl = sm8450_qmp_gen4x2_pcie_pcs_tbl, +- .pcs_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_pcs_tbl), +- .pcs_misc_tbl = sm8450_qmp_gen4x2_pcie_pcs_misc_tbl, +- .pcs_misc_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_pcs_misc_tbl), ++ .tables = { ++ .serdes = sm8450_qmp_gen4x2_pcie_serdes_tbl, ++ .serdes_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_serdes_tbl), ++ .tx = sm8450_qmp_gen4x2_pcie_tx_tbl, ++ .tx_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_tx_tbl), ++ .rx = sm8450_qmp_gen4x2_pcie_rx_tbl, ++ .rx_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_rx_tbl), ++ .pcs = sm8450_qmp_gen4x2_pcie_pcs_tbl, ++ .pcs_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_pcs_tbl), ++ .pcs_misc = sm8450_qmp_gen4x2_pcie_pcs_misc_tbl, ++ .pcs_misc_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_pcs_misc_tbl), ++ }, ++ ++ .tables_rc = &(const struct qmp_phy_cfg_tables) { ++ .serdes = sm8450_qmp_gen4x2_pcie_rc_serdes_tbl, ++ .serdes_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_rc_serdes_tbl), ++ .pcs_misc = sm8450_qmp_gen4x2_pcie_rc_pcs_misc_tbl, ++ .pcs_misc_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_rc_pcs_misc_tbl), ++ }, ++ ++ .tables_ep = &(const struct qmp_phy_cfg_tables) { ++ .serdes = sm8450_qmp_gen4x2_pcie_ep_serdes_tbl, ++ .serdes_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_ep_serdes_tbl), ++ .pcs_misc = sm8450_qmp_gen4x2_pcie_ep_pcs_misc_tbl, ++ .pcs_misc_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_ep_pcs_misc_tbl), ++ }, ++ + .clk_list = sdm845_pciephy_clk_l, + .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), + .reset_list = sdm845_pciephy_reset_l, +@@ -1813,10 +1862,6 @@ static const struct qmp_phy_cfg sm8450_qmp_gen4x2_pciephy_cfg = { + .start_ctrl = SERDES_START | PCS_START, + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS_4_20, +- +- .has_pwrdn_delay = true, +- .pwrdn_delay_min = 995, /* us */ +- .pwrdn_delay_max = 1005, /* us */ + }; + + static void qmp_pcie_configure_lane(void __iomem *base, +@@ -1850,17 +1895,49 @@ static void qmp_pcie_configure(void __iomem *base, + qmp_pcie_configure_lane(base, regs, tbl, num, 0xff); + } + +-static int qmp_pcie_serdes_init(struct qmp_phy *qphy) ++static void qmp_pcie_serdes_init(struct qmp_phy *qphy, const struct qmp_phy_cfg_tables *tables) + { + const struct qmp_phy_cfg *cfg = qphy->cfg; + void __iomem *serdes = qphy->serdes; +- const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; +- int serdes_tbl_num = cfg->serdes_tbl_num; + +- qmp_pcie_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); +- qmp_pcie_configure(serdes, cfg->regs, cfg->serdes_tbl_sec, cfg->serdes_tbl_num_sec); ++ if (!tables) ++ return; + +- return 0; ++ qmp_pcie_configure(serdes, cfg->regs, tables->serdes, tables->serdes_num); ++} ++ ++static void qmp_pcie_lanes_init(struct qmp_phy *qphy, const struct qmp_phy_cfg_tables *tables) ++{ ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *tx = qphy->tx; ++ void __iomem *rx = qphy->rx; ++ ++ if (!tables) ++ return; ++ ++ qmp_pcie_configure_lane(tx, cfg->regs, tables->tx, tables->tx_num, 1); ++ ++ if (cfg->lanes >= 2) ++ qmp_pcie_configure_lane(qphy->tx2, cfg->regs, tables->tx, tables->tx_num, 2); ++ ++ qmp_pcie_configure_lane(rx, cfg->regs, tables->rx, tables->rx_num, 1); ++ if (cfg->lanes >= 2) ++ qmp_pcie_configure_lane(qphy->rx2, cfg->regs, tables->rx, tables->rx_num, 2); ++} ++ ++static void qmp_pcie_pcs_init(struct qmp_phy *qphy, const struct qmp_phy_cfg_tables *tables) ++{ ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *pcs_misc = qphy->pcs_misc; ++ ++ if (!tables) ++ return; ++ ++ qmp_pcie_configure(pcs, cfg->regs, ++ tables->pcs, tables->pcs_num); ++ qmp_pcie_configure(pcs_misc, cfg->regs, ++ tables->pcs_misc, tables->pcs_misc_num); + } + + static int qmp_pcie_init(struct phy *phy) +@@ -1932,15 +2009,19 @@ static int qmp_pcie_power_on(struct phy *phy) + struct qmp_phy *qphy = phy_get_drvdata(phy); + struct qcom_qmp *qmp = qphy->qmp; + const struct qmp_phy_cfg *cfg = qphy->cfg; +- void __iomem *tx = qphy->tx; +- void __iomem *rx = qphy->rx; ++ const struct qmp_phy_cfg_tables *mode_tables; + void __iomem *pcs = qphy->pcs; +- void __iomem *pcs_misc = qphy->pcs_misc; + void __iomem *status; + unsigned int mask, val, ready; + int ret; + +- qmp_pcie_serdes_init(qphy); ++ if (qphy->mode == PHY_MODE_PCIE_RC) ++ mode_tables = cfg->tables_rc; ++ else ++ mode_tables = cfg->tables_ep; ++ ++ qmp_pcie_serdes_init(qphy, &cfg->tables); ++ qmp_pcie_serdes_init(qphy, mode_tables); + + ret = clk_prepare_enable(qphy->pipe_clk); + if (ret) { +@@ -1949,40 +2030,11 @@ static int qmp_pcie_power_on(struct phy *phy) + } + + /* Tx, Rx, and PCS configurations */ +- qmp_pcie_configure_lane(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num, 1); +- qmp_pcie_configure_lane(tx, cfg->regs, cfg->tx_tbl_sec, cfg->tx_tbl_num_sec, 1); +- +- if (cfg->lanes >= 2) { +- qmp_pcie_configure_lane(qphy->tx2, cfg->regs, cfg->tx_tbl, +- cfg->tx_tbl_num, 2); +- qmp_pcie_configure_lane(qphy->tx2, cfg->regs, cfg->tx_tbl_sec, +- cfg->tx_tbl_num_sec, 2); +- } +- +- qmp_pcie_configure_lane(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num, 1); +- qmp_pcie_configure_lane(rx, cfg->regs, cfg->rx_tbl_sec, cfg->rx_tbl_num_sec, 1); +- +- if (cfg->lanes >= 2) { +- qmp_pcie_configure_lane(qphy->rx2, cfg->regs, cfg->rx_tbl, +- cfg->rx_tbl_num, 2); +- qmp_pcie_configure_lane(qphy->rx2, cfg->regs, cfg->rx_tbl_sec, +- cfg->rx_tbl_num_sec, 2); +- } ++ qmp_pcie_lanes_init(qphy, &cfg->tables); ++ qmp_pcie_lanes_init(qphy, mode_tables); + +- qmp_pcie_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); +- qmp_pcie_configure(pcs, cfg->regs, cfg->pcs_tbl_sec, cfg->pcs_tbl_num_sec); +- +- qmp_pcie_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl, cfg->pcs_misc_tbl_num); +- qmp_pcie_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl_sec, cfg->pcs_misc_tbl_num_sec); +- +- /* +- * Pull out PHY from POWER DOWN state. +- * This is active low enable signal to power-down PHY. +- */ +- qphy_setbits(pcs, QPHY_V2_PCS_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl); +- +- if (cfg->has_pwrdn_delay) +- usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); ++ qmp_pcie_pcs_init(qphy, &cfg->tables); ++ qmp_pcie_pcs_init(qphy, mode_tables); + + /* Pull PHY out of reset state */ + qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); +@@ -1990,6 +2042,9 @@ static int qmp_pcie_power_on(struct phy *phy) + /* start SerDes and Phy-Coding-Sublayer */ + qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); + ++ if (!cfg->skip_start_delay) ++ usleep_range(1000, 1200); ++ + status = pcs + cfg->regs[QPHY_PCS_STATUS]; + mask = cfg->phy_status; + ready = 0; +@@ -2060,6 +2115,23 @@ static int qmp_pcie_disable(struct phy *phy) + return qmp_pcie_exit(phy); + } + ++static int qmp_pcie_set_mode(struct phy *phy, enum phy_mode mode, int submode) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ ++ switch (submode) { ++ case PHY_MODE_PCIE_RC: ++ case PHY_MODE_PCIE_EP: ++ qphy->mode = submode; ++ break; ++ default: ++ dev_err(&phy->dev, "Unsupported submode %d\n", submode); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + static int qmp_pcie_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) + { + struct qcom_qmp *qmp = dev_get_drvdata(dev); +@@ -2183,6 +2255,7 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) + static const struct phy_ops qmp_pcie_ops = { + .power_on = qmp_pcie_enable, + .power_off = qmp_pcie_disable, ++ .set_mode = qmp_pcie_set_mode, + .owner = THIS_MODULE, + }; + +@@ -2198,6 +2271,8 @@ static int qmp_pcie_create(struct device *dev, struct device_node *np, int id, + if (!qphy) + return -ENOMEM; + ++ qphy->mode = PHY_MODE_PCIE_RC; ++ + qphy->cfg = cfg; + qphy->serdes = serdes; + /* +@@ -2240,7 +2315,9 @@ static int qmp_pcie_create(struct device *dev, struct device_node *np, int id, + qphy->pcs_misc = qphy->pcs + 0x400; + + if (IS_ERR(qphy->pcs_misc)) { +- if (cfg->pcs_misc_tbl || cfg->pcs_misc_tbl_sec) ++ if (cfg->tables.pcs_misc || ++ (cfg->tables_rc && cfg->tables_rc->pcs_misc) || ++ (cfg->tables_ep && cfg->tables_ep->pcs_misc)) + return PTR_ERR(qphy->pcs_misc); + } + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v5_20.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v5_20.h +index 1eedf50cf9cbc..3d9713d348fe6 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v5_20.h ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v5_20.h +@@ -8,8 +8,10 @@ + + /* Only for QMP V5_20 PHY - PCIe PCS registers */ + #define QPHY_V5_20_PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x01c ++#define QPHY_V5_20_PCS_PCIE_OSC_DTCT_MODE2_CONFIG5 0x084 + #define QPHY_V5_20_PCS_PCIE_OSC_DTCT_ACTIONS 0x090 + #define QPHY_V5_20_PCS_PCIE_EQ_CONFIG1 0x0a0 ++#define QPHY_V5_20_PCS_PCIE_PRESET_P10_POST 0x0e0 + #define QPHY_V5_20_PCS_PCIE_G4_EQ_CONFIG5 0x108 + #define QPHY_V5_20_PCS_PCIE_G4_PRE_GAIN 0x15c + #define QPHY_V5_20_PCS_PCIE_RX_MARGINING_CONFIG3 0x184 +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v5_20.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v5_20.h +new file mode 100644 +index 0000000000000..9a5a20daf62cd +--- /dev/null ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v5_20.h +@@ -0,0 +1,14 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (c) 2022, Linaro Ltd. ++ */ ++ ++#ifndef QCOM_PHY_QMP_PCS_V5_20_H_ ++#define QCOM_PHY_QMP_PCS_V5_20_H_ ++ ++#define QPHY_V5_20_PCS_G3S2_PRE_GAIN 0x170 ++#define QPHY_V5_20_PCS_RX_SIGDET_LVL 0x188 ++#define QPHY_V5_20_PCS_EQ_CONFIG4 0x1e0 ++#define QPHY_V5_20_PCS_EQ_CONFIG5 0x1e4 ++ ++#endif +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +index b84c0d4b57541..f0ba35bb73c1b 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +@@ -63,8 +63,6 @@ + #define CLAMP_EN BIT(0) /* enables i/o clamp_n */ + + #define PHY_INIT_COMPLETE_TIMEOUT 10000 +-#define POWER_DOWN_DELAY_US_MIN 10 +-#define POWER_DOWN_DELAY_US_MAX 11 + + struct qmp_phy_init_tbl { + unsigned int offset; +@@ -126,6 +124,7 @@ static const unsigned int usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { + [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d4, + [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0d8, + [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x178, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x04, + }; + + static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { +@@ -135,6 +134,7 @@ static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { + [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d8, + [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0dc, + [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x170, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x04, + }; + + static const unsigned int qmp_v4_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { +@@ -1456,16 +1456,8 @@ struct qmp_phy_cfg { + /* array of registers with different offsets */ + const unsigned int *regs; + +- unsigned int start_ctrl; +- unsigned int pwrdn_ctrl; +- /* bit offset of PHYSTATUS in QPHY_PCS_STATUS register */ +- unsigned int phy_status; +- + /* true, if PHY needs delay after POWER_DOWN */ + bool has_pwrdn_delay; +- /* power_down delay in usec */ +- int pwrdn_delay_min; +- int pwrdn_delay_max; + + /* true, if PHY has a separate DP_COM control block */ + bool has_phy_dp_com_ctrl; +@@ -1616,11 +1608,7 @@ static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = { + .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), +- .regs = usb3phy_regs_layout, +- +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, ++ .regs = qmp_v3_usb3phy_regs_layout, + }; + + static const struct qmp_phy_cfg msm8996_usb3phy_cfg = { +@@ -1641,10 +1629,6 @@ static const struct qmp_phy_cfg msm8996_usb3phy_cfg = { + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = usb3phy_regs_layout, +- +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, + }; + + static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = { +@@ -1666,14 +1650,7 @@ static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = { + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = qmp_v3_usb3phy_regs_layout, + +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, +- + .has_pwrdn_delay = true, +- .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, +- .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, +- + .has_phy_dp_com_ctrl = true, + }; + +@@ -1696,14 +1673,7 @@ static const struct qmp_phy_cfg sc7180_usb3phy_cfg = { + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = qmp_v3_usb3phy_regs_layout, + +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, +- + .has_pwrdn_delay = true, +- .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, +- .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, +- + .has_phy_dp_com_ctrl = true, + }; + +@@ -1725,14 +1695,7 @@ static const struct qmp_phy_cfg sc8280xp_usb3_uniphy_cfg = { + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = qmp_v4_usb3phy_regs_layout, +- +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, +- +- .has_pwrdn_delay = true, +- .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, +- .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ .pcs_usb_offset = 0x1000, + }; + + static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { +@@ -1754,13 +1717,7 @@ static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = qmp_v3_usb3phy_regs_layout, + +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, +- + .has_pwrdn_delay = true, +- .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, +- .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, + }; + + static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { +@@ -1781,10 +1738,6 @@ static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = qmp_v3_usb3phy_regs_layout, +- +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, + }; + + static const struct qmp_phy_cfg sm8150_usb3phy_cfg = { +@@ -1809,15 +1762,7 @@ static const struct qmp_phy_cfg sm8150_usb3phy_cfg = { + .regs = qmp_v4_usb3phy_regs_layout, + .pcs_usb_offset = 0x300, + +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, +- +- + .has_pwrdn_delay = true, +- .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, +- .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, +- + .has_phy_dp_com_ctrl = true, + }; + +@@ -1843,13 +1788,7 @@ static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = { + .regs = qmp_v4_usb3phy_regs_layout, + .pcs_usb_offset = 0x600, + +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, +- + .has_pwrdn_delay = true, +- .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, +- .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, + }; + + static const struct qmp_phy_cfg sm8250_usb3phy_cfg = { +@@ -1874,14 +1813,7 @@ static const struct qmp_phy_cfg sm8250_usb3phy_cfg = { + .regs = qmp_v4_usb3phy_regs_layout, + .pcs_usb_offset = 0x300, + +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, +- + .has_pwrdn_delay = true, +- .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, +- .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, +- + .has_phy_dp_com_ctrl = true, + }; + +@@ -1907,13 +1839,7 @@ static const struct qmp_phy_cfg sm8250_usb3_uniphy_cfg = { + .regs = qmp_v4_usb3phy_regs_layout, + .pcs_usb_offset = 0x600, + +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, +- + .has_pwrdn_delay = true, +- .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, +- .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, + }; + + static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = { +@@ -1938,13 +1864,7 @@ static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = { + .regs = qmp_v4_usb3phy_regs_layout, + .pcs_usb_offset = 0x600, + +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, +- + .has_pwrdn_delay = true, +- .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, +- .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, + }; + + static const struct qmp_phy_cfg sdx65_usb3_uniphy_cfg = { +@@ -1969,13 +1889,7 @@ static const struct qmp_phy_cfg sdx65_usb3_uniphy_cfg = { + .regs = qmp_v4_usb3phy_regs_layout, + .pcs_usb_offset = 0x1000, + +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, +- + .has_pwrdn_delay = true, +- .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, +- .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, + }; + + static const struct qmp_phy_cfg sm8350_usb3phy_cfg = { +@@ -2000,14 +1914,7 @@ static const struct qmp_phy_cfg sm8350_usb3phy_cfg = { + .regs = qmp_v4_usb3phy_regs_layout, + .pcs_usb_offset = 0x300, + +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, +- + .has_pwrdn_delay = true, +- .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, +- .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, +- + .has_phy_dp_com_ctrl = true, + }; + +@@ -2033,13 +1940,7 @@ static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = { + .regs = qmp_v4_usb3phy_regs_layout, + .pcs_usb_offset = 0x1000, + +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, +- + .has_pwrdn_delay = true, +- .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, +- .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, + }; + + static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = { +@@ -2060,10 +1961,6 @@ static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = { + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = qcm2290_usb3phy_regs_layout, +- +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, + }; + + static void qmp_usb_configure_lane(void __iomem *base, +@@ -2164,13 +2061,7 @@ static int qmp_usb_init(struct phy *phy) + qphy_clrbits(dp_com, QPHY_V3_DP_COM_SW_RESET, SW_RESET); + } + +- if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) +- qphy_setbits(pcs, +- cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], +- cfg->pwrdn_ctrl); +- else +- qphy_setbits(pcs, QPHY_V2_PCS_POWER_DOWN_CONTROL, +- cfg->pwrdn_ctrl); ++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN); + + return 0; + +@@ -2206,7 +2097,7 @@ static int qmp_usb_power_on(struct phy *phy) + void __iomem *rx = qphy->rx; + void __iomem *pcs = qphy->pcs; + void __iomem *status; +- unsigned int mask, val, ready; ++ unsigned int val; + int ret; + + qmp_usb_serdes_init(qphy); +@@ -2236,19 +2127,16 @@ static int qmp_usb_power_on(struct phy *phy) + qmp_usb_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); + + if (cfg->has_pwrdn_delay) +- usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); ++ usleep_range(10, 20); + + /* Pull PHY out of reset state */ + qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); + + /* start SerDes and Phy-Coding-Sublayer */ +- qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); ++ qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], SERDES_START | PCS_START); + + status = pcs + cfg->regs[QPHY_PCS_STATUS]; +- mask = cfg->phy_status; +- ready = 0; +- +- ret = readl_poll_timeout(status, val, (val & mask) == ready, 10, ++ ret = readl_poll_timeout(status, val, !(val & PHYSTATUS), 10, + PHY_INIT_COMPLETE_TIMEOUT); + if (ret) { + dev_err(qmp->dev, "phy initialization timed-out\n"); +@@ -2274,16 +2162,12 @@ static int qmp_usb_power_off(struct phy *phy) + qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); + + /* stop SerDes and Phy-Coding-Sublayer */ +- qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); ++ qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], ++ SERDES_START | PCS_START); + + /* Put PHY into POWER DOWN state: active low */ +- if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) { +- qphy_clrbits(qphy->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], +- cfg->pwrdn_ctrl); +- } else { +- qphy_clrbits(qphy->pcs, QPHY_V2_PCS_POWER_DOWN_CONTROL, +- cfg->pwrdn_ctrl); +- } ++ qphy_clrbits(qphy->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], ++ SW_PWRDN); + + return 0; + } +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h +index 26274e3c0cf95..29a48f0436d2a 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp.h ++++ b/drivers/phy/qualcomm/phy-qcom-qmp.h +@@ -38,6 +38,7 @@ + #include "phy-qcom-qmp-pcs-pcie-v4_20.h" + + #include "phy-qcom-qmp-pcs-v5.h" ++#include "phy-qcom-qmp-pcs-v5_20.h" + #include "phy-qcom-qmp-pcs-pcie-v5.h" + #include "phy-qcom-qmp-pcs-usb-v5.h" + #include "phy-qcom-qmp-pcs-ufs-v5.h" +diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7986.c b/drivers/pinctrl/mediatek/pinctrl-mt7986.c +index 50cb736f9f116..b587299697481 100644 +--- a/drivers/pinctrl/mediatek/pinctrl-mt7986.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7986.c +@@ -316,10 +316,10 @@ static const struct mtk_pin_field_calc mt7986_pin_pupd_range[] = { + PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x30, 0x10, 9, 1), + PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x60, 0x10, 18, 1), + PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x60, 0x10, 12, 1), +- PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x60, 0x10, 22, 1), +- PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x60, 0x10, 20, 1), +- PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x60, 0x10, 26, 1), +- PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x60, 0x10, 24, 1), ++ PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x60, 0x10, 23, 1), ++ PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x60, 0x10, 21, 1), ++ PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x60, 0x10, 27, 1), ++ PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x60, 0x10, 25, 1), + PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x40, 0x10, 2, 1), + PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x40, 0x10, 1, 1), + PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x40, 0x10, 0, 1), +@@ -354,10 +354,10 @@ static const struct mtk_pin_field_calc mt7986_pin_r0_range[] = { + PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x40, 0x10, 9, 1), + PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x70, 0x10, 18, 1), + PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x70, 0x10, 12, 1), +- PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x70, 0x10, 22, 1), +- PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x70, 0x10, 20, 1), +- PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x70, 0x10, 26, 1), +- PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x70, 0x10, 24, 1), ++ PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x70, 0x10, 23, 1), ++ PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x70, 0x10, 21, 1), ++ PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x70, 0x10, 27, 1), ++ PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x70, 0x10, 25, 1), + PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x50, 0x10, 2, 1), + PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x50, 0x10, 1, 1), + PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x50, 0x10, 0, 1), +@@ -392,10 +392,10 @@ static const struct mtk_pin_field_calc mt7986_pin_r1_range[] = { + PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x50, 0x10, 9, 1), + PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x80, 0x10, 18, 1), + PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x80, 0x10, 12, 1), +- PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x80, 0x10, 22, 1), +- PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x80, 0x10, 20, 1), +- PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x80, 0x10, 26, 1), +- PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x80, 0x10, 24, 1), ++ PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x80, 0x10, 23, 1), ++ PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x80, 0x10, 21, 1), ++ PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x80, 0x10, 27, 1), ++ PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x80, 0x10, 25, 1), + PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x60, 0x10, 2, 1), + PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x60, 0x10, 1, 1), + PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x60, 0x10, 0, 1), +diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c +index 415d1df8f46a5..365c4b0ca4654 100644 +--- a/drivers/pinctrl/pinconf-generic.c ++++ b/drivers/pinctrl/pinconf-generic.c +@@ -395,8 +395,10 @@ int pinconf_generic_dt_node_to_map(struct pinctrl_dev *pctldev, + for_each_available_child_of_node(np_config, np) { + ret = pinconf_generic_dt_subnode_to_map(pctldev, np, map, + &reserved_maps, num_maps, type); +- if (ret < 0) ++ if (ret < 0) { ++ of_node_put(np); + goto exit; ++ } + } + return 0; + +diff --git a/drivers/pinctrl/pinctrl-k210.c b/drivers/pinctrl/pinctrl-k210.c +index ecab6bf63dc6d..ad4db99094a79 100644 +--- a/drivers/pinctrl/pinctrl-k210.c ++++ b/drivers/pinctrl/pinctrl-k210.c +@@ -862,8 +862,10 @@ static int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, + for_each_available_child_of_node(np_config, np) { + ret = k210_pinctrl_dt_subnode_to_map(pctldev, np, map, + &reserved_maps, num_maps); +- if (ret < 0) ++ if (ret < 0) { ++ of_node_put(np); + goto err; ++ } + } + return 0; + +diff --git a/drivers/pinctrl/pinctrl-ocelot.c b/drivers/pinctrl/pinctrl-ocelot.c +index 687aaa6015555..3d5995cbcb782 100644 +--- a/drivers/pinctrl/pinctrl-ocelot.c ++++ b/drivers/pinctrl/pinctrl-ocelot.c +@@ -2047,6 +2047,11 @@ static struct regmap *ocelot_pinctrl_create_pincfg(struct platform_device *pdev, + return devm_regmap_init_mmio(&pdev->dev, base, ®map_config); + } + ++static void ocelot_destroy_workqueue(void *data) ++{ ++ destroy_workqueue(data); ++} ++ + static int ocelot_pinctrl_probe(struct platform_device *pdev) + { + const struct ocelot_match_data *data; +@@ -2078,6 +2083,11 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev) + if (!info->wq) + return -ENOMEM; + ++ ret = devm_add_action_or_reset(dev, ocelot_destroy_workqueue, ++ info->wq); ++ if (ret) ++ return ret; ++ + info->pincfg_data = &data->pincfg_data; + + reset = devm_reset_control_get_optional_shared(dev, "switch"); +@@ -2119,15 +2129,6 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev) + return 0; + } + +-static int ocelot_pinctrl_remove(struct platform_device *pdev) +-{ +- struct ocelot_pinctrl *info = platform_get_drvdata(pdev); +- +- destroy_workqueue(info->wq); +- +- return 0; +-} +- + static struct platform_driver ocelot_pinctrl_driver = { + .driver = { + .name = "pinctrl-ocelot", +@@ -2135,7 +2136,6 @@ static struct platform_driver ocelot_pinctrl_driver = { + .suppress_bind_attrs = true, + }, + .probe = ocelot_pinctrl_probe, +- .remove = ocelot_pinctrl_remove, + }; + module_platform_driver(ocelot_pinctrl_driver); + +diff --git a/drivers/pinctrl/pinctrl-thunderbay.c b/drivers/pinctrl/pinctrl-thunderbay.c +index 9328b17485cf0..590bbbf619afc 100644 +--- a/drivers/pinctrl/pinctrl-thunderbay.c ++++ b/drivers/pinctrl/pinctrl-thunderbay.c +@@ -808,7 +808,7 @@ static int thunderbay_add_functions(struct thunderbay_pinctrl *tpc, struct funct + funcs[i].num_group_names, + funcs[i].data); + } +- kfree(funcs); ++ + return 0; + } + +@@ -817,6 +817,7 @@ static int thunderbay_build_functions(struct thunderbay_pinctrl *tpc) + struct function_desc *thunderbay_funcs; + void *ptr; + int pin; ++ int ret; + + /* + * Allocate maximum possible number of functions. Assume every pin +@@ -860,7 +861,10 @@ static int thunderbay_build_functions(struct thunderbay_pinctrl *tpc) + return -ENOMEM; + + thunderbay_funcs = ptr; +- return thunderbay_add_functions(tpc, thunderbay_funcs); ++ ret = thunderbay_add_functions(tpc, thunderbay_funcs); ++ ++ kfree(thunderbay_funcs); ++ return ret; + } + + static int thunderbay_pinconf_set_tristate(struct thunderbay_pinctrl *tpc, +diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c +index 2a7ff14dc37e9..59de4ce01faba 100644 +--- a/drivers/platform/chrome/cros_ec_typec.c ++++ b/drivers/platform/chrome/cros_ec_typec.c +@@ -173,10 +173,13 @@ static int cros_typec_get_switch_handles(struct cros_typec_port *port, + + role_sw_err: + typec_switch_put(port->ori_sw); ++ port->ori_sw = NULL; + ori_sw_err: + typec_retimer_put(port->retimer); ++ port->retimer = NULL; + retimer_sw_err: + typec_mux_put(port->mux); ++ port->mux = NULL; + mux_err: + return -ENODEV; + } +diff --git a/drivers/platform/chrome/cros_usbpd_notify.c b/drivers/platform/chrome/cros_usbpd_notify.c +index 4b5a81c9dc6da..10670b6588e3e 100644 +--- a/drivers/platform/chrome/cros_usbpd_notify.c ++++ b/drivers/platform/chrome/cros_usbpd_notify.c +@@ -239,7 +239,11 @@ static int __init cros_usbpd_notify_init(void) + return ret; + + #ifdef CONFIG_ACPI +- platform_driver_register(&cros_usbpd_notify_acpi_driver); ++ ret = platform_driver_register(&cros_usbpd_notify_acpi_driver); ++ if (ret) { ++ platform_driver_unregister(&cros_usbpd_notify_plat_driver); ++ return ret; ++ } + #endif + return 0; + } +diff --git a/drivers/platform/mellanox/mlxbf-pmc.c b/drivers/platform/mellanox/mlxbf-pmc.c +index 65b4a819f1bdf..c2c9b0d3244cb 100644 +--- a/drivers/platform/mellanox/mlxbf-pmc.c ++++ b/drivers/platform/mellanox/mlxbf-pmc.c +@@ -358,7 +358,7 @@ static const struct mlxbf_pmc_events mlxbf_pmc_hnfnet_events[] = { + { 0x32, "DDN_DIAG_W_INGRESS" }, + { 0x33, "DDN_DIAG_C_INGRESS" }, + { 0x34, "DDN_DIAG_CORE_SENT" }, +- { 0x35, "NDN_DIAG_S_OUT_OF_CRED" }, ++ { 0x35, "NDN_DIAG_N_OUT_OF_CRED" }, + { 0x36, "NDN_DIAG_S_OUT_OF_CRED" }, + { 0x37, "NDN_DIAG_E_OUT_OF_CRED" }, + { 0x38, "NDN_DIAG_W_OUT_OF_CRED" }, +diff --git a/drivers/platform/x86/huawei-wmi.c b/drivers/platform/x86/huawei-wmi.c +index 5873c2663a65b..b85050e4a0d65 100644 +--- a/drivers/platform/x86/huawei-wmi.c ++++ b/drivers/platform/x86/huawei-wmi.c +@@ -760,6 +760,9 @@ static int huawei_wmi_input_setup(struct device *dev, + const char *guid, + struct input_dev **idev) + { ++ acpi_status status; ++ int err; ++ + *idev = devm_input_allocate_device(dev); + if (!*idev) + return -ENOMEM; +@@ -769,10 +772,19 @@ static int huawei_wmi_input_setup(struct device *dev, + (*idev)->id.bustype = BUS_HOST; + (*idev)->dev.parent = dev; + +- return sparse_keymap_setup(*idev, huawei_wmi_keymap, NULL) || +- input_register_device(*idev) || +- wmi_install_notify_handler(guid, huawei_wmi_input_notify, +- *idev); ++ err = sparse_keymap_setup(*idev, huawei_wmi_keymap, NULL); ++ if (err) ++ return err; ++ ++ err = input_register_device(*idev); ++ if (err) ++ return err; ++ ++ status = wmi_install_notify_handler(guid, huawei_wmi_input_notify, *idev); ++ if (ACPI_FAILURE(status)) ++ return -EIO; ++ ++ return 0; + } + + static void huawei_wmi_input_exit(struct device *dev, const char *guid) +diff --git a/drivers/platform/x86/intel/int3472/clk_and_regulator.c b/drivers/platform/x86/intel/int3472/clk_and_regulator.c +index 1cf958983e868..b2342b3d78c72 100644 +--- a/drivers/platform/x86/intel/int3472/clk_and_regulator.c ++++ b/drivers/platform/x86/intel/int3472/clk_and_regulator.c +@@ -185,7 +185,8 @@ int skl_int3472_register_regulator(struct int3472_discrete_device *int3472, + cfg.init_data = &init_data; + cfg.ena_gpiod = int3472->regulator.gpio; + +- int3472->regulator.rdev = regulator_register(&int3472->regulator.rdesc, ++ int3472->regulator.rdev = regulator_register(int3472->dev, ++ &int3472->regulator.rdesc, + &cfg); + if (IS_ERR(int3472->regulator.rdev)) { + ret = PTR_ERR(int3472->regulator.rdev); +diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c +index 7cc9089d1e14f..e7a3e34028178 100644 +--- a/drivers/platform/x86/intel_scu_ipc.c ++++ b/drivers/platform/x86/intel_scu_ipc.c +@@ -583,7 +583,6 @@ __intel_scu_ipc_register(struct device *parent, + scu->dev.parent = parent; + scu->dev.class = &intel_scu_ipc_class; + scu->dev.release = intel_scu_ipc_release; +- dev_set_name(&scu->dev, "intel_scu_ipc"); + + if (!request_mem_region(scu_data->mem.start, resource_size(&scu_data->mem), + "intel_scu_ipc")) { +@@ -612,6 +611,7 @@ __intel_scu_ipc_register(struct device *parent, + * After this point intel_scu_ipc_release() takes care of + * releasing the SCU IPC resources once refcount drops to zero. + */ ++ dev_set_name(&scu->dev, "intel_scu_ipc"); + err = device_register(&scu->dev); + if (err) { + put_device(&scu->dev); +diff --git a/drivers/platform/x86/mxm-wmi.c b/drivers/platform/x86/mxm-wmi.c +index 9a19fbd2f7341..9a457956025a5 100644 +--- a/drivers/platform/x86/mxm-wmi.c ++++ b/drivers/platform/x86/mxm-wmi.c +@@ -35,13 +35,11 @@ int mxm_wmi_call_mxds(int adapter) + .xarg = 1, + }; + struct acpi_buffer input = { (acpi_size)sizeof(args), &args }; +- struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + acpi_status status; + + printk("calling mux switch %d\n", adapter); + +- status = wmi_evaluate_method(MXM_WMMX_GUID, 0x0, adapter, &input, +- &output); ++ status = wmi_evaluate_method(MXM_WMMX_GUID, 0x0, adapter, &input, NULL); + + if (ACPI_FAILURE(status)) + return status; +@@ -60,13 +58,11 @@ int mxm_wmi_call_mxmx(int adapter) + .xarg = 1, + }; + struct acpi_buffer input = { (acpi_size)sizeof(args), &args }; +- struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + acpi_status status; + + printk("calling mux switch %d\n", adapter); + +- status = wmi_evaluate_method(MXM_WMMX_GUID, 0x0, adapter, &input, +- &output); ++ status = wmi_evaluate_method(MXM_WMMX_GUID, 0x0, adapter, &input, NULL); + + if (ACPI_FAILURE(status)) + return status; +diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c +index 4df5aa6a309c3..6a60c5d83383b 100644 +--- a/drivers/pnp/core.c ++++ b/drivers/pnp/core.c +@@ -148,14 +148,14 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, + dev->dev.coherent_dma_mask = dev->dma_mask; + dev->dev.release = &pnp_release_device; + +- dev_set_name(&dev->dev, "%02x:%02x", dev->protocol->number, dev->number); +- + dev_id = pnp_add_id(dev, pnpid); + if (!dev_id) { + kfree(dev); + return NULL; + } + ++ dev_set_name(&dev->dev, "%02x:%02x", dev->protocol->number, dev->number); ++ + return dev; + } + +diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c +index c19c50442761d..58757a5799f8b 100644 +--- a/drivers/power/supply/ab8500_charger.c ++++ b/drivers/power/supply/ab8500_charger.c +@@ -3719,7 +3719,14 @@ static int __init ab8500_charger_init(void) + if (ret) + return ret; + +- return platform_driver_register(&ab8500_charger_driver); ++ ret = platform_driver_register(&ab8500_charger_driver); ++ if (ret) { ++ platform_unregister_drivers(ab8500_charger_component_drivers, ++ ARRAY_SIZE(ab8500_charger_component_drivers)); ++ return ret; ++ } ++ ++ return 0; + } + + static void __exit ab8500_charger_exit(void) +diff --git a/drivers/power/supply/bq25890_charger.c b/drivers/power/supply/bq25890_charger.c +index 6020b58c641d2..0e15302b8df22 100644 +--- a/drivers/power/supply/bq25890_charger.c ++++ b/drivers/power/supply/bq25890_charger.c +@@ -1049,6 +1049,36 @@ static const struct regulator_desc bq25890_vbus_desc = { + .fixed_uV = 5000000, + .n_voltages = 1, + }; ++ ++static int bq25890_register_regulator(struct bq25890_device *bq) ++{ ++ struct bq25890_platform_data *pdata = dev_get_platdata(bq->dev); ++ struct regulator_config cfg = { ++ .dev = bq->dev, ++ .driver_data = bq, ++ }; ++ struct regulator_dev *reg; ++ ++ if (!IS_ERR_OR_NULL(bq->usb_phy)) ++ return 0; ++ ++ if (pdata) ++ cfg.init_data = pdata->regulator_init_data; ++ ++ reg = devm_regulator_register(bq->dev, &bq25890_vbus_desc, &cfg); ++ if (IS_ERR(reg)) { ++ return dev_err_probe(bq->dev, PTR_ERR(reg), ++ "registering vbus regulator"); ++ } ++ ++ return 0; ++} ++#else ++static inline int ++bq25890_register_regulator(struct bq25890_device *bq) ++{ ++ return 0; ++} + #endif + + static int bq25890_get_chip_version(struct bq25890_device *bq) +@@ -1189,8 +1219,14 @@ static int bq25890_fw_probe(struct bq25890_device *bq) + return 0; + } + +-static int bq25890_probe(struct i2c_client *client, +- const struct i2c_device_id *id) ++static void bq25890_non_devm_cleanup(void *data) ++{ ++ struct bq25890_device *bq = data; ++ ++ cancel_delayed_work_sync(&bq->pump_express_work); ++} ++ ++static int bq25890_probe(struct i2c_client *client) + { + struct device *dev = &client->dev; + struct bq25890_device *bq; +@@ -1244,27 +1280,24 @@ static int bq25890_probe(struct i2c_client *client, + + /* OTG reporting */ + bq->usb_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); ++ ++ /* ++ * This must be before bq25890_power_supply_init(), so that it runs ++ * after devm unregisters the power_supply. ++ */ ++ ret = devm_add_action_or_reset(dev, bq25890_non_devm_cleanup, bq); ++ if (ret) ++ return ret; ++ ++ ret = bq25890_register_regulator(bq); ++ if (ret) ++ return ret; ++ + if (!IS_ERR_OR_NULL(bq->usb_phy)) { + INIT_WORK(&bq->usb_work, bq25890_usb_work); + bq->usb_nb.notifier_call = bq25890_usb_notifier; + usb_register_notifier(bq->usb_phy, &bq->usb_nb); + } +-#ifdef CONFIG_REGULATOR +- else { +- struct bq25890_platform_data *pdata = dev_get_platdata(dev); +- struct regulator_config cfg = { }; +- struct regulator_dev *reg; +- +- cfg.dev = dev; +- cfg.driver_data = bq; +- if (pdata) +- cfg.init_data = pdata->regulator_init_data; +- +- reg = devm_regulator_register(dev, &bq25890_vbus_desc, &cfg); +- if (IS_ERR(reg)) +- return dev_err_probe(dev, PTR_ERR(reg), "registering regulator"); +- } +-#endif + + ret = bq25890_power_supply_init(bq); + if (ret < 0) { +@@ -1400,7 +1433,7 @@ static struct i2c_driver bq25890_driver = { + .acpi_match_table = ACPI_PTR(bq25890_acpi_match), + .pm = &bq25890_pm, + }, +- .probe = bq25890_probe, ++ .probe_new = bq25890_probe, + .remove = bq25890_remove, + .shutdown = bq25890_shutdown, + .id_table = bq25890_i2c_ids, +diff --git a/drivers/power/supply/cw2015_battery.c b/drivers/power/supply/cw2015_battery.c +index 6d52641151d9a..473522b4326ad 100644 +--- a/drivers/power/supply/cw2015_battery.c ++++ b/drivers/power/supply/cw2015_battery.c +@@ -699,6 +699,9 @@ static int cw_bat_probe(struct i2c_client *client) + } + + cw_bat->battery_workqueue = create_singlethread_workqueue("rk_battery"); ++ if (!cw_bat->battery_workqueue) ++ return -ENOMEM; ++ + devm_delayed_work_autocancel(&client->dev, + &cw_bat->battery_delay_work, cw_bat_work); + queue_delayed_work(cw_bat->battery_workqueue, +diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c +index 4b5fb172fa994..01d1ac79d982e 100644 +--- a/drivers/power/supply/power_supply_core.c ++++ b/drivers/power/supply/power_supply_core.c +@@ -750,6 +750,11 @@ int power_supply_get_battery_info(struct power_supply *psy, + int i, tab_len, size; + + propname = kasprintf(GFP_KERNEL, "ocv-capacity-table-%d", index); ++ if (!propname) { ++ power_supply_put_battery_info(psy, info); ++ err = -ENOMEM; ++ goto out_put_node; ++ } + list = of_get_property(battery_np, propname, &size); + if (!list || !size) { + dev_err(&psy->dev, "failed to get %s\n", propname); +@@ -1387,8 +1392,8 @@ create_triggers_failed: + register_cooler_failed: + psy_unregister_thermal(psy); + register_thermal_failed: +- device_del(dev); + wakeup_init_failed: ++ device_del(dev); + device_add_failed: + check_supplies_failed: + dev_set_name_failed: +diff --git a/drivers/power/supply/rk817_charger.c b/drivers/power/supply/rk817_charger.c +index f20a6ac584ccd..4f9c1c4179165 100644 +--- a/drivers/power/supply/rk817_charger.c ++++ b/drivers/power/supply/rk817_charger.c +@@ -1060,8 +1060,10 @@ static int rk817_charger_probe(struct platform_device *pdev) + return -ENODEV; + + charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL); +- if (!charger) ++ if (!charger) { ++ of_node_put(node); + return -ENOMEM; ++ } + + charger->rk808 = rk808; + +diff --git a/drivers/power/supply/z2_battery.c b/drivers/power/supply/z2_battery.c +index 1897c29848600..d033c1d3ee42a 100644 +--- a/drivers/power/supply/z2_battery.c ++++ b/drivers/power/supply/z2_battery.c +@@ -206,10 +206,12 @@ static int z2_batt_probe(struct i2c_client *client, + + charger->charge_gpiod = devm_gpiod_get_optional(&client->dev, + NULL, GPIOD_IN); +- if (IS_ERR(charger->charge_gpiod)) +- return dev_err_probe(&client->dev, ++ if (IS_ERR(charger->charge_gpiod)) { ++ ret = dev_err_probe(&client->dev, + PTR_ERR(charger->charge_gpiod), + "failed to get charge GPIO\n"); ++ goto err; ++ } + + if (charger->charge_gpiod) { + gpiod_set_consumer_name(charger->charge_gpiod, "BATT CHRG"); +diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c +index 6901a44dc428d..a337b47dc2f7d 100644 +--- a/drivers/pwm/pwm-mediatek.c ++++ b/drivers/pwm/pwm-mediatek.c +@@ -296,7 +296,7 @@ static const struct pwm_mediatek_of_data mt6795_pwm_data = { + static const struct pwm_mediatek_of_data mt7622_pwm_data = { + .num_pwms = 6, + .pwm45_fixup = false, +- .has_ck_26m_sel = false, ++ .has_ck_26m_sel = true, + }; + + static const struct pwm_mediatek_of_data mt7623_pwm_data = { +diff --git a/drivers/pwm/pwm-mtk-disp.c b/drivers/pwm/pwm-mtk-disp.c +index c605013e4114c..3fbb4bae93a4e 100644 +--- a/drivers/pwm/pwm-mtk-disp.c ++++ b/drivers/pwm/pwm-mtk-disp.c +@@ -178,7 +178,7 @@ static void mtk_disp_pwm_get_state(struct pwm_chip *chip, + { + struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip); + u64 rate, period, high_width; +- u32 clk_div, con0, con1; ++ u32 clk_div, pwm_en, con0, con1; + int err; + + err = clk_prepare_enable(mdp->clk_main); +@@ -197,7 +197,8 @@ static void mtk_disp_pwm_get_state(struct pwm_chip *chip, + rate = clk_get_rate(mdp->clk_main); + con0 = readl(mdp->base + mdp->data->con0); + con1 = readl(mdp->base + mdp->data->con1); +- state->enabled = !!(con0 & BIT(0)); ++ pwm_en = readl(mdp->base + DISP_PWM_EN); ++ state->enabled = !!(pwm_en & mdp->data->enable_mask); + clk_div = FIELD_GET(PWM_CLKDIV_MASK, con0); + period = FIELD_GET(PWM_PERIOD_MASK, con1); + /* +diff --git a/drivers/pwm/pwm-sifive.c b/drivers/pwm/pwm-sifive.c +index 2d4fa5e5fdd46..bb72393134016 100644 +--- a/drivers/pwm/pwm-sifive.c ++++ b/drivers/pwm/pwm-sifive.c +@@ -204,8 +204,11 @@ static int pwm_sifive_clock_notifier(struct notifier_block *nb, + struct pwm_sifive_ddata *ddata = + container_of(nb, struct pwm_sifive_ddata, notifier); + +- if (event == POST_RATE_CHANGE) ++ if (event == POST_RATE_CHANGE) { ++ mutex_lock(&ddata->lock); + pwm_sifive_update_clock(ddata, ndata->new_rate); ++ mutex_unlock(&ddata->lock); ++ } + + return NOTIFY_OK; + } +diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c +index dad9978c91861..249dc01932979 100644 +--- a/drivers/pwm/pwm-tegra.c ++++ b/drivers/pwm/pwm-tegra.c +@@ -145,8 +145,19 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + * source clock rate as required_clk_rate, PWM controller will + * be able to configure the requested period. + */ +- required_clk_rate = +- (NSEC_PER_SEC / period_ns) << PWM_DUTY_WIDTH; ++ required_clk_rate = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC << PWM_DUTY_WIDTH, ++ period_ns); ++ ++ if (required_clk_rate > clk_round_rate(pc->clk, required_clk_rate)) ++ /* ++ * required_clk_rate is a lower bound for the input ++ * rate; for lower rates there is no value for PWM_SCALE ++ * that yields a period less than or equal to the ++ * requested period. Hence, for lower rates, double the ++ * required_clk_rate to get a clock rate that can meet ++ * the requested period. ++ */ ++ required_clk_rate *= 2; + + err = dev_pm_opp_set_rate(pc->dev, required_clk_rate); + if (err < 0) +diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c +index 2cdc054e53a53..43db495f19861 100644 +--- a/drivers/rapidio/devices/rio_mport_cdev.c ++++ b/drivers/rapidio/devices/rio_mport_cdev.c +@@ -1804,8 +1804,11 @@ static int rio_mport_add_riodev(struct mport_cdev_priv *priv, + rio_init_dbell_res(&rdev->riores[RIO_DOORBELL_RESOURCE], + 0, 0xffff); + err = rio_add_device(rdev); +- if (err) +- goto cleanup; ++ if (err) { ++ put_device(&rdev->dev); ++ return err; ++ } ++ + rio_dev_get(rdev); + + return 0; +@@ -1901,10 +1904,6 @@ static int mport_cdev_open(struct inode *inode, struct file *filp) + + priv->md = chdev; + +- mutex_lock(&chdev->file_mutex); +- list_add_tail(&priv->list, &chdev->file_list); +- mutex_unlock(&chdev->file_mutex); +- + INIT_LIST_HEAD(&priv->db_filters); + INIT_LIST_HEAD(&priv->pw_filters); + spin_lock_init(&priv->fifo_lock); +@@ -1913,6 +1912,7 @@ static int mport_cdev_open(struct inode *inode, struct file *filp) + sizeof(struct rio_event) * MPORT_EVENT_DEPTH, + GFP_KERNEL); + if (ret < 0) { ++ put_device(&chdev->dev); + dev_err(&chdev->dev, DRV_NAME ": kfifo_alloc failed\n"); + ret = -ENOMEM; + goto err_fifo; +@@ -1923,6 +1923,9 @@ static int mport_cdev_open(struct inode *inode, struct file *filp) + spin_lock_init(&priv->req_lock); + mutex_init(&priv->dma_lock); + #endif ++ mutex_lock(&chdev->file_mutex); ++ list_add_tail(&priv->list, &chdev->file_list); ++ mutex_unlock(&chdev->file_mutex); + + filp->private_data = priv; + goto out; +diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c +index 19b0c33f4a62a..fdcf742b2adbc 100644 +--- a/drivers/rapidio/rio-scan.c ++++ b/drivers/rapidio/rio-scan.c +@@ -454,8 +454,12 @@ static struct rio_dev *rio_setup_device(struct rio_net *net, + 0, 0xffff); + + ret = rio_add_device(rdev); +- if (ret) +- goto cleanup; ++ if (ret) { ++ if (rswitch) ++ kfree(rswitch->route_table); ++ put_device(&rdev->dev); ++ return NULL; ++ } + + rio_dev_get(rdev); + +diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c +index e74cf09eeff07..9544b8ee0c963 100644 +--- a/drivers/rapidio/rio.c ++++ b/drivers/rapidio/rio.c +@@ -2186,11 +2186,16 @@ int rio_register_mport(struct rio_mport *port) + atomic_set(&port->state, RIO_DEVICE_RUNNING); + + res = device_register(&port->dev); +- if (res) ++ if (res) { + dev_err(&port->dev, "RIO: mport%d registration failed ERR=%d\n", + port->id, res); +- else ++ mutex_lock(&rio_mport_list_lock); ++ list_del(&port->node); ++ mutex_unlock(&rio_mport_list_lock); ++ put_device(&port->dev); ++ } else { + dev_dbg(&port->dev, "RIO: registered mport%d\n", port->id); ++ } + + return res; + } +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index e8c00a884f1f1..3716ba060368c 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -1002,7 +1002,7 @@ static int drms_uA_update(struct regulator_dev *rdev) + /* get input voltage */ + input_uV = 0; + if (rdev->supply) +- input_uV = regulator_get_voltage(rdev->supply); ++ input_uV = regulator_get_voltage_rdev(rdev->supply->rdev); + if (input_uV <= 0) + input_uV = rdev->constraints->input_uV; + +@@ -1596,7 +1596,13 @@ static int set_machine_constraints(struct regulator_dev *rdev) + if (rdev->supply_name && !rdev->supply) + return -EPROBE_DEFER; + +- if (rdev->supply) { ++ /* If supplying regulator has already been enabled, ++ * it's not intended to have use_count increment ++ * when rdev is only boot-on. ++ */ ++ if (rdev->supply && ++ (rdev->constraints->always_on || ++ !regulator_is_enabled(rdev->supply))) { + ret = regulator_enable(rdev->supply); + if (ret < 0) { + _regulator_put(rdev->supply); +@@ -1640,6 +1646,7 @@ static int set_supply(struct regulator_dev *rdev, + + rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); + if (rdev->supply == NULL) { ++ module_put(supply_rdev->owner); + err = -ENOMEM; + return err; + } +@@ -1813,7 +1820,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, + + regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); + if (regulator == NULL) { +- kfree(supply_name); ++ kfree_const(supply_name); + return NULL; + } + +@@ -1943,6 +1950,7 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev, + node = of_get_regulator(dev, supply); + if (node) { + r = of_find_regulator_by_node(node); ++ of_node_put(node); + if (r) + return r; + +@@ -5396,6 +5404,7 @@ static struct regulator_coupler generic_regulator_coupler = { + + /** + * regulator_register - register regulator ++ * @dev: the device that drive the regulator + * @regulator_desc: regulator to register + * @cfg: runtime configuration for regulator + * +@@ -5404,7 +5413,8 @@ static struct regulator_coupler generic_regulator_coupler = { + * or an ERR_PTR() on error. + */ + struct regulator_dev * +-regulator_register(const struct regulator_desc *regulator_desc, ++regulator_register(struct device *dev, ++ const struct regulator_desc *regulator_desc, + const struct regulator_config *cfg) + { + const struct regulator_init_data *init_data; +@@ -5413,7 +5423,6 @@ regulator_register(const struct regulator_desc *regulator_desc, + struct regulator_dev *rdev; + bool dangling_cfg_gpiod = false; + bool dangling_of_gpiod = false; +- struct device *dev; + int ret, i; + bool resolved_early = false; + +@@ -5426,8 +5435,7 @@ regulator_register(const struct regulator_desc *regulator_desc, + goto rinse; + } + +- dev = cfg->dev; +- WARN_ON(!dev); ++ WARN_ON(!dev || !cfg->dev); + + if (regulator_desc->name == NULL || regulator_desc->ops == NULL) { + ret = -EINVAL; +@@ -5526,7 +5534,7 @@ regulator_register(const struct regulator_desc *regulator_desc, + + /* register with sysfs */ + rdev->dev.class = ®ulator_class; +- rdev->dev.parent = dev; ++ rdev->dev.parent = config->dev; + dev_set_name(&rdev->dev, "regulator.%lu", + (unsigned long) atomic_inc_return(®ulator_no)); + dev_set_drvdata(&rdev->dev, rdev); +@@ -5641,6 +5649,7 @@ unset_supplies: + regulator_remove_coupling(rdev); + mutex_unlock(®ulator_list_mutex); + wash: ++ regulator_put(rdev->supply); + kfree(rdev->coupling_desc.coupled_rdevs); + mutex_lock(®ulator_list_mutex); + regulator_ena_gpio_free(rdev); +diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c +index 3265e75e97ab4..5c7ff9b3e8a79 100644 +--- a/drivers/regulator/devres.c ++++ b/drivers/regulator/devres.c +@@ -385,7 +385,7 @@ struct regulator_dev *devm_regulator_register(struct device *dev, + if (!ptr) + return ERR_PTR(-ENOMEM); + +- rdev = regulator_register(regulator_desc, config); ++ rdev = regulator_register(dev, regulator_desc, config); + if (!IS_ERR(rdev)) { + *ptr = rdev; + devres_add(dev, ptr); +diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c +index 0aff1c2886b5d..cd726d4e8fbfb 100644 +--- a/drivers/regulator/of_regulator.c ++++ b/drivers/regulator/of_regulator.c +@@ -505,7 +505,7 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev, + struct device_node *child; + struct regulator_init_data *init_data = NULL; + +- child = regulator_of_get_init_node(dev, desc); ++ child = regulator_of_get_init_node(config->dev, desc); + if (!child) + return NULL; + +diff --git a/drivers/regulator/qcom-labibb-regulator.c b/drivers/regulator/qcom-labibb-regulator.c +index 639b71eb41ffe..bcf7140f3bc98 100644 +--- a/drivers/regulator/qcom-labibb-regulator.c ++++ b/drivers/regulator/qcom-labibb-regulator.c +@@ -822,6 +822,7 @@ static int qcom_labibb_regulator_probe(struct platform_device *pdev) + if (irq == 0) + irq = -EINVAL; + ++ of_node_put(reg_node); + return dev_err_probe(vreg->dev, irq, + "Short-circuit irq not found.\n"); + } +diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c +index 4158ff126a67a..f90bcdeecea58 100644 +--- a/drivers/regulator/qcom-rpmh-regulator.c ++++ b/drivers/regulator/qcom-rpmh-regulator.c +@@ -1187,7 +1187,7 @@ static const struct rpmh_vreg_init_data pm7325_vreg_data[] = { + static const struct rpmh_vreg_init_data pmr735a_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps520, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps520, "vdd-s2"), +- RPMH_VREG("smps3", "smp%s3", &pmic5_hfsmps510, "vdd-s3"), ++ RPMH_VREG("smps3", "smp%s3", &pmic5_hfsmps515, "vdd-s3"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1-l2"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l1-l2"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"), +diff --git a/drivers/regulator/stm32-vrefbuf.c b/drivers/regulator/stm32-vrefbuf.c +index 30ea3bc8ca192..7a454b7b6eab9 100644 +--- a/drivers/regulator/stm32-vrefbuf.c ++++ b/drivers/regulator/stm32-vrefbuf.c +@@ -210,7 +210,7 @@ static int stm32_vrefbuf_probe(struct platform_device *pdev) + pdev->dev.of_node, + &stm32_vrefbuf_regu); + +- rdev = regulator_register(&stm32_vrefbuf_regu, &config); ++ rdev = regulator_register(&pdev->dev, &stm32_vrefbuf_regu, &config); + if (IS_ERR(rdev)) { + ret = PTR_ERR(rdev); + dev_err(&pdev->dev, "register failed with error %d\n", ret); +diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c +index 6afd0941e5524..dc6f07ca83410 100644 +--- a/drivers/remoteproc/qcom_q6v5_pas.c ++++ b/drivers/remoteproc/qcom_q6v5_pas.c +@@ -449,6 +449,7 @@ static int adsp_alloc_memory_region(struct qcom_adsp *adsp) + } + + ret = of_address_to_resource(node, 0, &r); ++ of_node_put(node); + if (ret) + return ret; + +@@ -556,6 +557,7 @@ static int adsp_probe(struct platform_device *pdev) + detach_proxy_pds: + adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count); + free_rproc: ++ device_init_wakeup(adsp->dev, false); + rproc_free(rproc); + + return ret; +@@ -572,6 +574,8 @@ static int adsp_remove(struct platform_device *pdev) + qcom_remove_sysmon_subdev(adsp->sysmon); + qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev); + qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev); ++ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count); ++ device_init_wakeup(adsp->dev, false); + rproc_free(adsp->rproc); + + return 0; +diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c +index bb0947f7770ea..ba24d745b2d65 100644 +--- a/drivers/remoteproc/qcom_q6v5_wcss.c ++++ b/drivers/remoteproc/qcom_q6v5_wcss.c +@@ -351,7 +351,7 @@ static int q6v5_wcss_qcs404_power_on(struct q6v5_wcss *wcss) + if (ret) { + dev_err(wcss->dev, + "xo cbcr enabling timed out (rc:%d)\n", ret); +- return ret; ++ goto disable_xo_cbcr_clk; + } + + writel(0, wcss->reg_base + Q6SS_CGC_OVERRIDE); +@@ -417,6 +417,7 @@ disable_sleep_cbcr_clk: + val = readl(wcss->reg_base + Q6SS_SLEEP_CBCR); + val &= ~Q6SS_CLK_ENABLE; + writel(val, wcss->reg_base + Q6SS_SLEEP_CBCR); ++disable_xo_cbcr_clk: + val = readl(wcss->reg_base + Q6SS_XO_CBCR); + val &= ~Q6SS_CLK_ENABLE; + writel(val, wcss->reg_base + Q6SS_XO_CBCR); +@@ -827,6 +828,9 @@ static int q6v5_wcss_init_mmio(struct q6v5_wcss *wcss, + int ret; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qdsp6"); ++ if (!res) ++ return -EINVAL; ++ + wcss->reg_base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!wcss->reg_base) +diff --git a/drivers/remoteproc/qcom_sysmon.c b/drivers/remoteproc/qcom_sysmon.c +index 57dde2a69b9dd..15af52f8499eb 100644 +--- a/drivers/remoteproc/qcom_sysmon.c ++++ b/drivers/remoteproc/qcom_sysmon.c +@@ -652,7 +652,9 @@ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc, + if (sysmon->shutdown_irq != -ENODATA) { + dev_err(sysmon->dev, + "failed to retrieve shutdown-ack IRQ\n"); +- return ERR_PTR(sysmon->shutdown_irq); ++ ret = sysmon->shutdown_irq; ++ kfree(sysmon); ++ return ERR_PTR(ret); + } + } else { + ret = devm_request_threaded_irq(sysmon->dev, +@@ -663,6 +665,7 @@ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc, + if (ret) { + dev_err(sysmon->dev, + "failed to acquire shutdown-ack IRQ\n"); ++ kfree(sysmon); + return ERR_PTR(ret); + } + } +diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c +index 8768cb64f560c..cb1d414a23896 100644 +--- a/drivers/remoteproc/remoteproc_core.c ++++ b/drivers/remoteproc/remoteproc_core.c +@@ -509,7 +509,13 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr, + rvdev_data.rsc_offset = offset; + rvdev_data.rsc = rsc; + +- pdev = platform_device_register_data(dev, "rproc-virtio", rvdev_data.index, &rvdev_data, ++ /* ++ * When there is more than one remote processor, rproc->nb_vdev number is ++ * same for each separate instances of "rproc". If rvdev_data.index is used ++ * as device id, then we get duplication in sysfs, so need to use ++ * PLATFORM_DEVID_AUTO to auto select device id. ++ */ ++ pdev = platform_device_register_data(dev, "rproc-virtio", PLATFORM_DEVID_AUTO, &rvdev_data, + sizeof(rvdev_data)); + if (IS_ERR(pdev)) { + dev_err(dev, "failed to create rproc-virtio device\n"); +diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c +index e48223c00c672..e5b7b48cffac0 100644 +--- a/drivers/rtc/class.c ++++ b/drivers/rtc/class.c +@@ -374,11 +374,11 @@ struct rtc_device *devm_rtc_allocate_device(struct device *dev) + + rtc->id = id; + rtc->dev.parent = dev; +- err = dev_set_name(&rtc->dev, "rtc%d", id); ++ err = devm_add_action_or_reset(dev, devm_rtc_release_device, rtc); + if (err) + return ERR_PTR(err); + +- err = devm_add_action_or_reset(dev, devm_rtc_release_device, rtc); ++ err = dev_set_name(&rtc->dev, "rtc%d", id); + if (err) + return ERR_PTR(err); + +diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c +index 58cc2bae2f8a0..00e2ca7374ecf 100644 +--- a/drivers/rtc/rtc-cmos.c ++++ b/drivers/rtc/rtc-cmos.c +@@ -744,6 +744,168 @@ static irqreturn_t cmos_interrupt(int irq, void *p) + return IRQ_NONE; + } + ++#ifdef CONFIG_ACPI ++ ++#include <linux/acpi.h> ++ ++static u32 rtc_handler(void *context) ++{ ++ struct device *dev = context; ++ struct cmos_rtc *cmos = dev_get_drvdata(dev); ++ unsigned char rtc_control = 0; ++ unsigned char rtc_intr; ++ unsigned long flags; ++ ++ ++ /* ++ * Always update rtc irq when ACPI is used as RTC Alarm. ++ * Or else, ACPI SCI is enabled during suspend/resume only, ++ * update rtc irq in that case. ++ */ ++ if (cmos_use_acpi_alarm()) ++ cmos_interrupt(0, (void *)cmos->rtc); ++ else { ++ /* Fix me: can we use cmos_interrupt() here as well? */ ++ spin_lock_irqsave(&rtc_lock, flags); ++ if (cmos_rtc.suspend_ctrl) ++ rtc_control = CMOS_READ(RTC_CONTROL); ++ if (rtc_control & RTC_AIE) { ++ cmos_rtc.suspend_ctrl &= ~RTC_AIE; ++ CMOS_WRITE(rtc_control, RTC_CONTROL); ++ rtc_intr = CMOS_READ(RTC_INTR_FLAGS); ++ rtc_update_irq(cmos->rtc, 1, rtc_intr); ++ } ++ spin_unlock_irqrestore(&rtc_lock, flags); ++ } ++ ++ pm_wakeup_hard_event(dev); ++ acpi_clear_event(ACPI_EVENT_RTC); ++ acpi_disable_event(ACPI_EVENT_RTC, 0); ++ return ACPI_INTERRUPT_HANDLED; ++} ++ ++static void acpi_rtc_event_setup(struct device *dev) ++{ ++ if (acpi_disabled) ++ return; ++ ++ acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, dev); ++ /* ++ * After the RTC handler is installed, the Fixed_RTC event should ++ * be disabled. Only when the RTC alarm is set will it be enabled. ++ */ ++ acpi_clear_event(ACPI_EVENT_RTC); ++ acpi_disable_event(ACPI_EVENT_RTC, 0); ++} ++ ++static void acpi_rtc_event_cleanup(void) ++{ ++ if (acpi_disabled) ++ return; ++ ++ acpi_remove_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler); ++} ++ ++static void rtc_wake_on(struct device *dev) ++{ ++ acpi_clear_event(ACPI_EVENT_RTC); ++ acpi_enable_event(ACPI_EVENT_RTC, 0); ++} ++ ++static void rtc_wake_off(struct device *dev) ++{ ++ acpi_disable_event(ACPI_EVENT_RTC, 0); ++} ++ ++#ifdef CONFIG_X86 ++/* Enable use_acpi_alarm mode for Intel platforms no earlier than 2015 */ ++static void use_acpi_alarm_quirks(void) ++{ ++ if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) ++ return; ++ ++ if (!is_hpet_enabled()) ++ return; ++ ++ if (dmi_get_bios_year() < 2015) ++ return; ++ ++ use_acpi_alarm = true; ++} ++#else ++static inline void use_acpi_alarm_quirks(void) { } ++#endif ++ ++static void acpi_cmos_wake_setup(struct device *dev) ++{ ++ if (acpi_disabled) ++ return; ++ ++ use_acpi_alarm_quirks(); ++ ++ cmos_rtc.wake_on = rtc_wake_on; ++ cmos_rtc.wake_off = rtc_wake_off; ++ ++ /* ACPI tables bug workaround. */ ++ if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) { ++ dev_dbg(dev, "bogus FADT month_alarm (%d)\n", ++ acpi_gbl_FADT.month_alarm); ++ acpi_gbl_FADT.month_alarm = 0; ++ } ++ ++ cmos_rtc.day_alrm = acpi_gbl_FADT.day_alarm; ++ cmos_rtc.mon_alrm = acpi_gbl_FADT.month_alarm; ++ cmos_rtc.century = acpi_gbl_FADT.century; ++ ++ if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE) ++ dev_info(dev, "RTC can wake from S4\n"); ++ ++ /* RTC always wakes from S1/S2/S3, and often S4/STD */ ++ device_init_wakeup(dev, 1); ++} ++ ++static void cmos_check_acpi_rtc_status(struct device *dev, ++ unsigned char *rtc_control) ++{ ++ struct cmos_rtc *cmos = dev_get_drvdata(dev); ++ acpi_event_status rtc_status; ++ acpi_status status; ++ ++ if (acpi_gbl_FADT.flags & ACPI_FADT_FIXED_RTC) ++ return; ++ ++ status = acpi_get_event_status(ACPI_EVENT_RTC, &rtc_status); ++ if (ACPI_FAILURE(status)) { ++ dev_err(dev, "Could not get RTC status\n"); ++ } else if (rtc_status & ACPI_EVENT_FLAG_SET) { ++ unsigned char mask; ++ *rtc_control &= ~RTC_AIE; ++ CMOS_WRITE(*rtc_control, RTC_CONTROL); ++ mask = CMOS_READ(RTC_INTR_FLAGS); ++ rtc_update_irq(cmos->rtc, 1, mask); ++ } ++} ++ ++#else /* !CONFIG_ACPI */ ++ ++static inline void acpi_rtc_event_setup(struct device *dev) ++{ ++} ++ ++static inline void acpi_rtc_event_cleanup(void) ++{ ++} ++ ++static inline void acpi_cmos_wake_setup(struct device *dev) ++{ ++} ++ ++static inline void cmos_check_acpi_rtc_status(struct device *dev, ++ unsigned char *rtc_control) ++{ ++} ++#endif /* CONFIG_ACPI */ ++ + #ifdef CONFIG_PNP + #define INITSECTION + +@@ -827,19 +989,27 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) + if (info->address_space) + address_space = info->address_space; + +- if (info->rtc_day_alarm && info->rtc_day_alarm < 128) +- cmos_rtc.day_alrm = info->rtc_day_alarm; +- if (info->rtc_mon_alarm && info->rtc_mon_alarm < 128) +- cmos_rtc.mon_alrm = info->rtc_mon_alarm; +- if (info->rtc_century && info->rtc_century < 128) +- cmos_rtc.century = info->rtc_century; ++ cmos_rtc.day_alrm = info->rtc_day_alarm; ++ cmos_rtc.mon_alrm = info->rtc_mon_alarm; ++ cmos_rtc.century = info->rtc_century; + + if (info->wake_on && info->wake_off) { + cmos_rtc.wake_on = info->wake_on; + cmos_rtc.wake_off = info->wake_off; + } ++ } else { ++ acpi_cmos_wake_setup(dev); + } + ++ if (cmos_rtc.day_alrm >= 128) ++ cmos_rtc.day_alrm = 0; ++ ++ if (cmos_rtc.mon_alrm >= 128) ++ cmos_rtc.mon_alrm = 0; ++ ++ if (cmos_rtc.century >= 128) ++ cmos_rtc.century = 0; ++ + cmos_rtc.dev = dev; + dev_set_drvdata(dev, &cmos_rtc); + +@@ -928,6 +1098,13 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) + nvmem_cfg.size = address_space - NVRAM_OFFSET; + devm_rtc_nvmem_register(cmos_rtc.rtc, &nvmem_cfg); + ++ /* ++ * Everything has gone well so far, so by default register a handler for ++ * the ACPI RTC fixed event. ++ */ ++ if (!info) ++ acpi_rtc_event_setup(dev); ++ + dev_info(dev, "%s%s, %d bytes nvram%s\n", + !is_valid_irq(rtc_irq) ? "no alarms" : + cmos_rtc.mon_alrm ? "alarms up to one year" : +@@ -973,6 +1150,9 @@ static void cmos_do_remove(struct device *dev) + hpet_unregister_irq_handler(cmos_interrupt); + } + ++ if (!dev_get_platdata(dev)) ++ acpi_rtc_event_cleanup(); ++ + cmos->rtc = NULL; + + ports = cmos->iomem; +@@ -1122,9 +1302,6 @@ static void cmos_check_wkalrm(struct device *dev) + } + } + +-static void cmos_check_acpi_rtc_status(struct device *dev, +- unsigned char *rtc_control); +- + static int __maybe_unused cmos_resume(struct device *dev) + { + struct cmos_rtc *cmos = dev_get_drvdata(dev); +@@ -1191,175 +1368,13 @@ static SIMPLE_DEV_PM_OPS(cmos_pm_ops, cmos_suspend, cmos_resume); + * predate even PNPBIOS should set up platform_bus devices. + */ + +-#ifdef CONFIG_ACPI +- +-#include <linux/acpi.h> +- +-static u32 rtc_handler(void *context) +-{ +- struct device *dev = context; +- struct cmos_rtc *cmos = dev_get_drvdata(dev); +- unsigned char rtc_control = 0; +- unsigned char rtc_intr; +- unsigned long flags; +- +- +- /* +- * Always update rtc irq when ACPI is used as RTC Alarm. +- * Or else, ACPI SCI is enabled during suspend/resume only, +- * update rtc irq in that case. +- */ +- if (cmos_use_acpi_alarm()) +- cmos_interrupt(0, (void *)cmos->rtc); +- else { +- /* Fix me: can we use cmos_interrupt() here as well? */ +- spin_lock_irqsave(&rtc_lock, flags); +- if (cmos_rtc.suspend_ctrl) +- rtc_control = CMOS_READ(RTC_CONTROL); +- if (rtc_control & RTC_AIE) { +- cmos_rtc.suspend_ctrl &= ~RTC_AIE; +- CMOS_WRITE(rtc_control, RTC_CONTROL); +- rtc_intr = CMOS_READ(RTC_INTR_FLAGS); +- rtc_update_irq(cmos->rtc, 1, rtc_intr); +- } +- spin_unlock_irqrestore(&rtc_lock, flags); +- } +- +- pm_wakeup_hard_event(dev); +- acpi_clear_event(ACPI_EVENT_RTC); +- acpi_disable_event(ACPI_EVENT_RTC, 0); +- return ACPI_INTERRUPT_HANDLED; +-} +- +-static inline void rtc_wake_setup(struct device *dev) +-{ +- if (acpi_disabled) +- return; +- +- acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, dev); +- /* +- * After the RTC handler is installed, the Fixed_RTC event should +- * be disabled. Only when the RTC alarm is set will it be enabled. +- */ +- acpi_clear_event(ACPI_EVENT_RTC); +- acpi_disable_event(ACPI_EVENT_RTC, 0); +-} +- +-static void rtc_wake_on(struct device *dev) +-{ +- acpi_clear_event(ACPI_EVENT_RTC); +- acpi_enable_event(ACPI_EVENT_RTC, 0); +-} +- +-static void rtc_wake_off(struct device *dev) +-{ +- acpi_disable_event(ACPI_EVENT_RTC, 0); +-} +- +-#ifdef CONFIG_X86 +-/* Enable use_acpi_alarm mode for Intel platforms no earlier than 2015 */ +-static void use_acpi_alarm_quirks(void) +-{ +- if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) +- return; +- +- if (!is_hpet_enabled()) +- return; +- +- if (dmi_get_bios_year() < 2015) +- return; +- +- use_acpi_alarm = true; +-} +-#else +-static inline void use_acpi_alarm_quirks(void) { } +-#endif +- +-/* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find +- * its device node and pass extra config data. This helps its driver use +- * capabilities that the now-obsolete mc146818 didn't have, and informs it +- * that this board's RTC is wakeup-capable (per ACPI spec). +- */ +-static struct cmos_rtc_board_info acpi_rtc_info; +- +-static void cmos_wake_setup(struct device *dev) +-{ +- if (acpi_disabled) +- return; +- +- use_acpi_alarm_quirks(); +- +- acpi_rtc_info.wake_on = rtc_wake_on; +- acpi_rtc_info.wake_off = rtc_wake_off; +- +- /* workaround bug in some ACPI tables */ +- if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) { +- dev_dbg(dev, "bogus FADT month_alarm (%d)\n", +- acpi_gbl_FADT.month_alarm); +- acpi_gbl_FADT.month_alarm = 0; +- } +- +- acpi_rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm; +- acpi_rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm; +- acpi_rtc_info.rtc_century = acpi_gbl_FADT.century; +- +- /* NOTE: S4_RTC_WAKE is NOT currently useful to Linux */ +- if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE) +- dev_info(dev, "RTC can wake from S4\n"); +- +- dev->platform_data = &acpi_rtc_info; +- +- /* RTC always wakes from S1/S2/S3, and often S4/STD */ +- device_init_wakeup(dev, 1); +-} +- +-static void cmos_check_acpi_rtc_status(struct device *dev, +- unsigned char *rtc_control) +-{ +- struct cmos_rtc *cmos = dev_get_drvdata(dev); +- acpi_event_status rtc_status; +- acpi_status status; +- +- if (acpi_gbl_FADT.flags & ACPI_FADT_FIXED_RTC) +- return; +- +- status = acpi_get_event_status(ACPI_EVENT_RTC, &rtc_status); +- if (ACPI_FAILURE(status)) { +- dev_err(dev, "Could not get RTC status\n"); +- } else if (rtc_status & ACPI_EVENT_FLAG_SET) { +- unsigned char mask; +- *rtc_control &= ~RTC_AIE; +- CMOS_WRITE(*rtc_control, RTC_CONTROL); +- mask = CMOS_READ(RTC_INTR_FLAGS); +- rtc_update_irq(cmos->rtc, 1, mask); +- } +-} +- +-#else +- +-static void cmos_wake_setup(struct device *dev) +-{ +-} +- +-static void cmos_check_acpi_rtc_status(struct device *dev, +- unsigned char *rtc_control) +-{ +-} +- +-static void rtc_wake_setup(struct device *dev) +-{ +-} +-#endif +- + #ifdef CONFIG_PNP + + #include <linux/pnp.h> + + static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) + { +- int irq, ret; +- +- cmos_wake_setup(&pnp->dev); ++ int irq; + + if (pnp_port_start(pnp, 0) == 0x70 && !pnp_irq_valid(pnp, 0)) { + irq = 0; +@@ -1375,13 +1390,7 @@ static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) + irq = pnp_irq(pnp, 0); + } + +- ret = cmos_do_probe(&pnp->dev, pnp_get_resource(pnp, IORESOURCE_IO, 0), irq); +- if (ret) +- return ret; +- +- rtc_wake_setup(&pnp->dev); +- +- return 0; ++ return cmos_do_probe(&pnp->dev, pnp_get_resource(pnp, IORESOURCE_IO, 0), irq); + } + + static void cmos_pnp_remove(struct pnp_dev *pnp) +@@ -1465,10 +1474,9 @@ static inline void cmos_of_init(struct platform_device *pdev) {} + static int __init cmos_platform_probe(struct platform_device *pdev) + { + struct resource *resource; +- int irq, ret; ++ int irq; + + cmos_of_init(pdev); +- cmos_wake_setup(&pdev->dev); + + if (RTC_IOMAPPED) + resource = platform_get_resource(pdev, IORESOURCE_IO, 0); +@@ -1478,13 +1486,7 @@ static int __init cmos_platform_probe(struct platform_device *pdev) + if (irq < 0) + irq = -1; + +- ret = cmos_do_probe(&pdev->dev, resource, irq); +- if (ret) +- return ret; +- +- rtc_wake_setup(&pdev->dev); +- +- return 0; ++ return cmos_do_probe(&pdev->dev, resource, irq); + } + + static int cmos_platform_remove(struct platform_device *pdev) +diff --git a/drivers/rtc/rtc-msc313.c b/drivers/rtc/rtc-msc313.c +index f3fde013c4b8b..8d7737e0e2e02 100644 +--- a/drivers/rtc/rtc-msc313.c ++++ b/drivers/rtc/rtc-msc313.c +@@ -212,22 +212,12 @@ static int msc313_rtc_probe(struct platform_device *pdev) + return ret; + } + +- clk = devm_clk_get(dev, NULL); ++ clk = devm_clk_get_enabled(dev, NULL); + if (IS_ERR(clk)) { + dev_err(dev, "No input reference clock\n"); + return PTR_ERR(clk); + } + +- ret = clk_prepare_enable(clk); +- if (ret) { +- dev_err(dev, "Failed to enable the reference clock, %d\n", ret); +- return ret; +- } +- +- ret = devm_add_action_or_reset(dev, (void (*) (void *))clk_disable_unprepare, clk); +- if (ret) +- return ret; +- + rate = clk_get_rate(clk); + writew(rate & 0xFFFF, priv->rtc_base + REG_RTC_FREQ_CW_L); + writew((rate >> 16) & 0xFFFF, priv->rtc_base + REG_RTC_FREQ_CW_H); +diff --git a/drivers/rtc/rtc-mxc_v2.c b/drivers/rtc/rtc-mxc_v2.c +index 5e03834016294..f6d2ad91ff7a9 100644 +--- a/drivers/rtc/rtc-mxc_v2.c ++++ b/drivers/rtc/rtc-mxc_v2.c +@@ -336,8 +336,10 @@ static int mxc_rtc_probe(struct platform_device *pdev) + } + + pdata->rtc = devm_rtc_allocate_device(&pdev->dev); +- if (IS_ERR(pdata->rtc)) ++ if (IS_ERR(pdata->rtc)) { ++ clk_disable_unprepare(pdata->clk); + return PTR_ERR(pdata->rtc); ++ } + + pdata->rtc->ops = &mxc_rtc_ops; + pdata->rtc->range_max = U32_MAX; +diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c +index 63b275b014bd6..87f4fc9df68b4 100644 +--- a/drivers/rtc/rtc-pcf2127.c ++++ b/drivers/rtc/rtc-pcf2127.c +@@ -885,9 +885,17 @@ static const struct regmap_bus pcf2127_i2c_regmap = { + + static struct i2c_driver pcf2127_i2c_driver; + +-static int pcf2127_i2c_probe(struct i2c_client *client, +- const struct i2c_device_id *id) ++static const struct i2c_device_id pcf2127_i2c_id[] = { ++ { "pcf2127", 1 }, ++ { "pcf2129", 0 }, ++ { "pca2129", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, pcf2127_i2c_id); ++ ++static int pcf2127_i2c_probe(struct i2c_client *client) + { ++ const struct i2c_device_id *id = i2c_match_id(pcf2127_i2c_id, client); + struct regmap *regmap; + static const struct regmap_config config = { + .reg_bits = 8, +@@ -910,20 +918,12 @@ static int pcf2127_i2c_probe(struct i2c_client *client, + pcf2127_i2c_driver.driver.name, id->driver_data); + } + +-static const struct i2c_device_id pcf2127_i2c_id[] = { +- { "pcf2127", 1 }, +- { "pcf2129", 0 }, +- { "pca2129", 0 }, +- { } +-}; +-MODULE_DEVICE_TABLE(i2c, pcf2127_i2c_id); +- + static struct i2c_driver pcf2127_i2c_driver = { + .driver = { + .name = "rtc-pcf2127-i2c", + .of_match_table = of_match_ptr(pcf2127_of_match), + }, +- .probe = pcf2127_i2c_probe, ++ .probe_new = pcf2127_i2c_probe, + .id_table = pcf2127_i2c_id, + }; + +diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c +index 095891999da11..754e03984f986 100644 +--- a/drivers/rtc/rtc-pcf85063.c ++++ b/drivers/rtc/rtc-pcf85063.c +@@ -169,10 +169,10 @@ static int pcf85063_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) + if (ret) + return ret; + +- alrm->time.tm_sec = bcd2bin(buf[0]); +- alrm->time.tm_min = bcd2bin(buf[1]); +- alrm->time.tm_hour = bcd2bin(buf[2]); +- alrm->time.tm_mday = bcd2bin(buf[3]); ++ alrm->time.tm_sec = bcd2bin(buf[0] & 0x7f); ++ alrm->time.tm_min = bcd2bin(buf[1] & 0x7f); ++ alrm->time.tm_hour = bcd2bin(buf[2] & 0x3f); ++ alrm->time.tm_mday = bcd2bin(buf[3] & 0x3f); + + ret = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL2, &val); + if (ret) +@@ -424,7 +424,7 @@ static int pcf85063_clkout_control(struct clk_hw *hw, bool enable) + unsigned int buf; + int ret; + +- ret = regmap_read(pcf85063->regmap, PCF85063_REG_OFFSET, &buf); ++ ret = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL2, &buf); + if (ret < 0) + return ret; + buf &= PCF85063_REG_CLKO_F_MASK; +diff --git a/drivers/rtc/rtc-pic32.c b/drivers/rtc/rtc-pic32.c +index 7fb9145c43bd5..fa351ac201587 100644 +--- a/drivers/rtc/rtc-pic32.c ++++ b/drivers/rtc/rtc-pic32.c +@@ -324,16 +324,16 @@ static int pic32_rtc_probe(struct platform_device *pdev) + + spin_lock_init(&pdata->alarm_lock); + ++ pdata->rtc = devm_rtc_allocate_device(&pdev->dev); ++ if (IS_ERR(pdata->rtc)) ++ return PTR_ERR(pdata->rtc); ++ + clk_prepare_enable(pdata->clk); + + pic32_rtc_enable(pdata, 1); + + device_init_wakeup(&pdev->dev, 1); + +- pdata->rtc = devm_rtc_allocate_device(&pdev->dev); +- if (IS_ERR(pdata->rtc)) +- return PTR_ERR(pdata->rtc); +- + pdata->rtc->ops = &pic32_rtcops; + pdata->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + pdata->rtc->range_max = RTC_TIMESTAMP_END_2099; +diff --git a/drivers/rtc/rtc-rzn1.c b/drivers/rtc/rtc-rzn1.c +index ac788799c8e3e..0d36bc50197c1 100644 +--- a/drivers/rtc/rtc-rzn1.c ++++ b/drivers/rtc/rtc-rzn1.c +@@ -355,7 +355,9 @@ static int rzn1_rtc_probe(struct platform_device *pdev) + set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->rtcdev->features); + clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->rtcdev->features); + +- devm_pm_runtime_enable(&pdev->dev); ++ ret = devm_pm_runtime_enable(&pdev->dev); ++ if (ret < 0) ++ return ret; + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret < 0) + return ret; +diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c +index bd929b0e7d7de..d82acf1af1fae 100644 +--- a/drivers/rtc/rtc-snvs.c ++++ b/drivers/rtc/rtc-snvs.c +@@ -32,6 +32,14 @@ + #define SNVS_LPPGDR_INIT 0x41736166 + #define CNTR_TO_SECS_SH 15 + ++/* The maximum RTC clock cycles that are allowed to pass between two ++ * consecutive clock counter register reads. If the values are corrupted a ++ * bigger difference is expected. The RTC frequency is 32kHz. With 320 cycles ++ * we end at 10ms which should be enough for most cases. If it once takes ++ * longer than expected we do a retry. ++ */ ++#define MAX_RTC_READ_DIFF_CYCLES 320 ++ + struct snvs_rtc_data { + struct rtc_device *rtc; + struct regmap *regmap; +@@ -56,6 +64,7 @@ static u64 rtc_read_lpsrt(struct snvs_rtc_data *data) + static u32 rtc_read_lp_counter(struct snvs_rtc_data *data) + { + u64 read1, read2; ++ s64 diff; + unsigned int timeout = 100; + + /* As expected, the registers might update between the read of the LSB +@@ -66,7 +75,8 @@ static u32 rtc_read_lp_counter(struct snvs_rtc_data *data) + do { + read2 = read1; + read1 = rtc_read_lpsrt(data); +- } while (read1 != read2 && --timeout); ++ diff = read1 - read2; ++ } while (((diff < 0) || (diff > MAX_RTC_READ_DIFF_CYCLES)) && --timeout); + if (!timeout) + dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n"); + +@@ -78,13 +88,15 @@ static u32 rtc_read_lp_counter(struct snvs_rtc_data *data) + static int rtc_read_lp_counter_lsb(struct snvs_rtc_data *data, u32 *lsb) + { + u32 count1, count2; ++ s32 diff; + unsigned int timeout = 100; + + regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1); + do { + count2 = count1; + regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1); +- } while (count1 != count2 && --timeout); ++ diff = count1 - count2; ++ } while (((diff < 0) || (diff > MAX_RTC_READ_DIFF_CYCLES)) && --timeout); + if (!timeout) { + dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n"); + return -ETIMEDOUT; +diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c +index bdb20f63254e2..0f8e4231098ef 100644 +--- a/drivers/rtc/rtc-st-lpc.c ++++ b/drivers/rtc/rtc-st-lpc.c +@@ -238,6 +238,7 @@ static int st_rtc_probe(struct platform_device *pdev) + + rtc->clkrate = clk_get_rate(rtc->clk); + if (!rtc->clkrate) { ++ clk_disable_unprepare(rtc->clk); + dev_err(&pdev->dev, "Unable to fetch clock rate\n"); + return -EINVAL; + } +diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c +index 37b551bd43bff..bdfab9ea00464 100644 +--- a/drivers/s390/net/ctcm_main.c ++++ b/drivers/s390/net/ctcm_main.c +@@ -825,16 +825,9 @@ done: + /* + * Start transmission of a packet. + * Called from generic network device layer. +- * +- * skb Pointer to buffer containing the packet. +- * dev Pointer to interface struct. +- * +- * returns 0 if packet consumed, !0 if packet rejected. +- * Note: If we return !0, then the packet is free'd by +- * the generic network layer. + */ + /* first merge version - leaving both functions separated */ +-static int ctcm_tx(struct sk_buff *skb, struct net_device *dev) ++static netdev_tx_t ctcm_tx(struct sk_buff *skb, struct net_device *dev) + { + struct ctcm_priv *priv = dev->ml_priv; + +@@ -877,7 +870,7 @@ static int ctcm_tx(struct sk_buff *skb, struct net_device *dev) + } + + /* unmerged MPC variant of ctcm_tx */ +-static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev) ++static netdev_tx_t ctcmpc_tx(struct sk_buff *skb, struct net_device *dev) + { + int len = 0; + struct ctcm_priv *priv = dev->ml_priv; +diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c +index 84c8981317b46..38f312664ce72 100644 +--- a/drivers/s390/net/lcs.c ++++ b/drivers/s390/net/lcs.c +@@ -1519,9 +1519,8 @@ lcs_txbuffer_cb(struct lcs_channel *channel, struct lcs_buffer *buffer) + /* + * Packet transmit function called by network stack + */ +-static int +-__lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb, +- struct net_device *dev) ++static netdev_tx_t __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb, ++ struct net_device *dev) + { + struct lcs_header *header; + int rc = NETDEV_TX_OK; +@@ -1582,8 +1581,7 @@ out: + return rc; + } + +-static int +-lcs_start_xmit(struct sk_buff *skb, struct net_device *dev) ++static netdev_tx_t lcs_start_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct lcs_card *card; + int rc; +diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c +index 65aa0a96c21de..66076cada8ae4 100644 +--- a/drivers/s390/net/netiucv.c ++++ b/drivers/s390/net/netiucv.c +@@ -1248,15 +1248,8 @@ static int netiucv_close(struct net_device *dev) + /* + * Start transmission of a packet. + * Called from generic network device layer. +- * +- * @param skb Pointer to buffer containing the packet. +- * @param dev Pointer to interface struct. +- * +- * @return 0 if packet consumed, !0 if packet rejected. +- * Note: If we return !0, then the packet is free'd by +- * the generic network layer. + */ +-static int netiucv_tx(struct sk_buff *skb, struct net_device *dev) ++static netdev_tx_t netiucv_tx(struct sk_buff *skb, struct net_device *dev) + { + struct netiucv_priv *privptr = netdev_priv(dev); + int rc; +diff --git a/drivers/scsi/elx/efct/efct_driver.c b/drivers/scsi/elx/efct/efct_driver.c +index b08fc8839808d..49fd2cfed70c7 100644 +--- a/drivers/scsi/elx/efct/efct_driver.c ++++ b/drivers/scsi/elx/efct/efct_driver.c +@@ -42,6 +42,7 @@ efct_device_init(void) + + rc = efct_scsi_reg_fc_transport(); + if (rc) { ++ efct_scsi_tgt_driver_exit(); + pr_err("failed to register to FC host\n"); + return rc; + } +diff --git a/drivers/scsi/elx/libefc/efclib.h b/drivers/scsi/elx/libefc/efclib.h +index dde20891c2dd7..57e3386128127 100644 +--- a/drivers/scsi/elx/libefc/efclib.h ++++ b/drivers/scsi/elx/libefc/efclib.h +@@ -58,10 +58,12 @@ enum efc_node_send_ls_acc { + #define EFC_LINK_STATUS_UP 0 + #define EFC_LINK_STATUS_DOWN 1 + ++enum efc_sm_event; ++ + /* State machine context header */ + struct efc_sm_ctx { + void (*current_state)(struct efc_sm_ctx *ctx, +- u32 evt, void *arg); ++ enum efc_sm_event evt, void *arg); + + const char *description; + void *app; +@@ -365,7 +367,7 @@ struct efc_node { + int prev_evt; + + void (*nodedb_state)(struct efc_sm_ctx *ctx, +- u32 evt, void *arg); ++ enum efc_sm_event evt, void *arg); + struct timer_list gidpt_delay_timer; + u64 time_last_gidpt_msec; + +diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c +index 6ec296321ffc1..38774a272e627 100644 +--- a/drivers/scsi/fcoe/fcoe.c ++++ b/drivers/scsi/fcoe/fcoe.c +@@ -2491,6 +2491,7 @@ static int __init fcoe_init(void) + + out_free: + mutex_unlock(&fcoe_config_mutex); ++ fcoe_transport_detach(&fcoe_sw_transport); + out_destroy: + destroy_workqueue(fcoe_wq); + return rc; +diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c +index af658aa38fedf..6260aa5ea6af8 100644 +--- a/drivers/scsi/fcoe/fcoe_sysfs.c ++++ b/drivers/scsi/fcoe/fcoe_sysfs.c +@@ -830,14 +830,15 @@ struct fcoe_ctlr_device *fcoe_ctlr_device_add(struct device *parent, + + dev_set_name(&ctlr->dev, "ctlr_%d", ctlr->id); + error = device_register(&ctlr->dev); +- if (error) +- goto out_del_q2; ++ if (error) { ++ destroy_workqueue(ctlr->devloss_work_q); ++ destroy_workqueue(ctlr->work_q); ++ put_device(&ctlr->dev); ++ return NULL; ++ } + + return ctlr; + +-out_del_q2: +- destroy_workqueue(ctlr->devloss_work_q); +- ctlr->devloss_work_q = NULL; + out_del_q: + destroy_workqueue(ctlr->work_q); + ctlr->work_q = NULL; +@@ -1036,16 +1037,16 @@ struct fcoe_fcf_device *fcoe_fcf_device_add(struct fcoe_ctlr_device *ctlr, + fcf->selected = new_fcf->selected; + + error = device_register(&fcf->dev); +- if (error) +- goto out_del; ++ if (error) { ++ put_device(&fcf->dev); ++ goto out; ++ } + + fcf->state = FCOE_FCF_STATE_CONNECTED; + list_add_tail(&fcf->peers, &ctlr->fcfs); + + return fcf; + +-out_del: +- kfree(fcf); + out: + return NULL; + } +diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c +index f8e832b1bc46a..4dbf51e2623ad 100644 +--- a/drivers/scsi/hpsa.c ++++ b/drivers/scsi/hpsa.c +@@ -8925,7 +8925,7 @@ clean1: /* wq/aer/h */ + destroy_workqueue(h->monitor_ctlr_wq); + h->monitor_ctlr_wq = NULL; + } +- kfree(h); ++ hpda_free_ctlr_info(h); + return rc; + } + +@@ -9786,7 +9786,8 @@ static int hpsa_add_sas_host(struct ctlr_info *h) + return 0; + + free_sas_phy: +- hpsa_free_sas_phy(hpsa_sas_phy); ++ sas_phy_free(hpsa_sas_phy->phy); ++ kfree(hpsa_sas_phy); + free_sas_port: + hpsa_free_sas_port(hpsa_sas_port); + free_sas_node: +@@ -9822,10 +9823,12 @@ static int hpsa_add_sas_device(struct hpsa_sas_node *hpsa_sas_node, + + rc = hpsa_sas_port_add_rphy(hpsa_sas_port, rphy); + if (rc) +- goto free_sas_port; ++ goto free_sas_rphy; + + return 0; + ++free_sas_rphy: ++ sas_rphy_free(rphy); + free_sas_port: + hpsa_free_sas_port(hpsa_sas_port); + device->sas_port = NULL; +diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c +index 9d01a3e3c26aa..2022ffb450417 100644 +--- a/drivers/scsi/ipr.c ++++ b/drivers/scsi/ipr.c +@@ -10872,11 +10872,19 @@ static struct notifier_block ipr_notifier = { + **/ + static int __init ipr_init(void) + { ++ int rc; ++ + ipr_info("IBM Power RAID SCSI Device Driver version: %s %s\n", + IPR_DRIVER_VERSION, IPR_DRIVER_DATE); + + register_reboot_notifier(&ipr_notifier); +- return pci_register_driver(&ipr_driver); ++ rc = pci_register_driver(&ipr_driver); ++ if (rc) { ++ unregister_reboot_notifier(&ipr_notifier); ++ return rc; ++ } ++ ++ return 0; + } + + /** +diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c +index 99d06dc7ddf6b..21c52154626f1 100644 +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -8150,10 +8150,10 @@ u32 lpfc_rx_monitor_report(struct lpfc_hba *phba, + "IO_cnt", "Info", "BWutil(ms)"); + } + +- /* Needs to be _bh because record is called from timer interrupt ++ /* Needs to be _irq because record is called from timer interrupt + * context + */ +- spin_lock_bh(ring_lock); ++ spin_lock_irq(ring_lock); + while (*head_idx != *tail_idx) { + entry = &ring[*head_idx]; + +@@ -8197,7 +8197,7 @@ u32 lpfc_rx_monitor_report(struct lpfc_hba *phba, + if (cnt >= max_read_entries) + break; + } +- spin_unlock_bh(ring_lock); ++ spin_unlock_irq(ring_lock); + + return cnt; + } +diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c +index 0681daee6c149..e5ecd6ada6cdd 100644 +--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c ++++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c +@@ -829,6 +829,8 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, + if ((sas_rphy_add(rphy))) { + ioc_err(ioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); ++ sas_rphy_free(rphy); ++ rphy = NULL; + } + + if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) { +diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h +index 802eec6407d9a..a26a373be9da3 100644 +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -5136,17 +5136,17 @@ struct secure_flash_update_block_pk { + (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || \ + test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) + +-#define QLA_VHA_MARK_BUSY(__vha, __bail) do { \ +- atomic_inc(&__vha->vref_count); \ +- mb(); \ +- if (__vha->flags.delete_progress) { \ +- atomic_dec(&__vha->vref_count); \ +- wake_up(&__vha->vref_waitq); \ +- __bail = 1; \ +- } else { \ +- __bail = 0; \ +- } \ +-} while (0) ++static inline bool qla_vha_mark_busy(scsi_qla_host_t *vha) ++{ ++ atomic_inc(&vha->vref_count); ++ mb(); ++ if (vha->flags.delete_progress) { ++ atomic_dec(&vha->vref_count); ++ wake_up(&vha->vref_waitq); ++ return true; ++ } ++ return false; ++} + + #define QLA_VHA_MARK_NOT_BUSY(__vha) do { \ + atomic_dec(&__vha->vref_count); \ +diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c +index e12db95de6883..432f47fc5e1f3 100644 +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -110,6 +110,7 @@ static void qla24xx_abort_iocb_timeout(void *data) + struct qla_qpair *qpair = sp->qpair; + u32 handle; + unsigned long flags; ++ int sp_found = 0, cmdsp_found = 0; + + if (sp->cmd_sp) + ql_dbg(ql_dbg_async, sp->vha, 0x507c, +@@ -124,18 +125,21 @@ static void qla24xx_abort_iocb_timeout(void *data) + spin_lock_irqsave(qpair->qp_lock_ptr, flags); + for (handle = 1; handle < qpair->req->num_outstanding_cmds; handle++) { + if (sp->cmd_sp && (qpair->req->outstanding_cmds[handle] == +- sp->cmd_sp)) ++ sp->cmd_sp)) { + qpair->req->outstanding_cmds[handle] = NULL; ++ cmdsp_found = 1; ++ } + + /* removing the abort */ + if (qpair->req->outstanding_cmds[handle] == sp) { + qpair->req->outstanding_cmds[handle] = NULL; ++ sp_found = 1; + break; + } + } + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + +- if (sp->cmd_sp) { ++ if (cmdsp_found && sp->cmd_sp) { + /* + * This done function should take care of + * original command ref: INIT +@@ -143,8 +147,10 @@ static void qla24xx_abort_iocb_timeout(void *data) + sp->cmd_sp->done(sp->cmd_sp, QLA_OS_TIMER_EXPIRED); + } + +- abt->u.abt.comp_status = cpu_to_le16(CS_TIMEOUT); +- sp->done(sp, QLA_OS_TIMER_EXPIRED); ++ if (sp_found) { ++ abt->u.abt.comp_status = cpu_to_le16(CS_TIMEOUT); ++ sp->done(sp, QLA_OS_TIMER_EXPIRED); ++ } + } + + static void qla24xx_abort_sp_done(srb_t *sp, int res) +@@ -168,7 +174,6 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait) + struct srb_iocb *abt_iocb; + srb_t *sp; + int rval = QLA_FUNCTION_FAILED; +- uint8_t bail; + + /* ref: INIT for ABTS command */ + sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp->fcport, +@@ -176,7 +181,7 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait) + if (!sp) + return QLA_MEMORY_ALLOC_FAILED; + +- QLA_VHA_MARK_BUSY(vha, bail); ++ qla_vha_mark_busy(vha); + abt_iocb = &sp->u.iocb_cmd; + sp->type = SRB_ABT_CMD; + sp->name = "abort"; +@@ -2020,14 +2025,13 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, + struct srb_iocb *tm_iocb; + srb_t *sp; + int rval = QLA_FUNCTION_FAILED; +- uint8_t bail; + + /* ref: INIT */ + sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); + if (!sp) + goto done; + +- QLA_VHA_MARK_BUSY(vha, bail); ++ qla_vha_mark_busy(vha); + sp->type = SRB_TM_CMD; + sp->name = "tmf"; + qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha), +diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h +index db17f7f410cdd..5185dc5daf80d 100644 +--- a/drivers/scsi/qla2xxx/qla_inline.h ++++ b/drivers/scsi/qla2xxx/qla_inline.h +@@ -225,11 +225,9 @@ static inline srb_t * + qla2x00_get_sp(scsi_qla_host_t *vha, fc_port_t *fcport, gfp_t flag) + { + srb_t *sp = NULL; +- uint8_t bail; + struct qla_qpair *qpair; + +- QLA_VHA_MARK_BUSY(vha, bail); +- if (unlikely(bail)) ++ if (unlikely(qla_vha_mark_busy(vha))) + return NULL; + + qpair = vha->hw->base_qpair; +diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c +index 2c85f3cce7264..96ba1398f20c1 100644 +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -5069,13 +5069,11 @@ struct qla_work_evt * + qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type) + { + struct qla_work_evt *e; +- uint8_t bail; + + if (test_bit(UNLOADING, &vha->dpc_flags)) + return NULL; + +- QLA_VHA_MARK_BUSY(vha, bail); +- if (bail) ++ if (qla_vha_mark_busy(vha)) + return NULL; + + e = kzalloc(sizeof(struct qla_work_evt), GFP_ATOMIC); +diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c +index bebda917b1383..b77035ddc9440 100644 +--- a/drivers/scsi/scsi_debug.c ++++ b/drivers/scsi/scsi_debug.c +@@ -3785,7 +3785,7 @@ static int resp_write_scat(struct scsi_cmnd *scp, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); + return illegal_condition_result; + } +- lrdp = kzalloc(lbdof_blen, GFP_ATOMIC); ++ lrdp = kzalloc(lbdof_blen, GFP_ATOMIC | __GFP_NOWARN); + if (lrdp == NULL) + return SCSI_MLQUEUE_HOST_BUSY; + if (sdebug_verbose) +@@ -4436,7 +4436,7 @@ static int resp_verify(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) + if (ret) + return ret; + +- arr = kcalloc(lb_size, vnum, GFP_ATOMIC); ++ arr = kcalloc(lb_size, vnum, GFP_ATOMIC | __GFP_NOWARN); + if (!arr) { + mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, + INSUFF_RES_ASCQ); +@@ -4504,7 +4504,7 @@ static int resp_report_zones(struct scsi_cmnd *scp, + + rep_max_zones = (alloc_len - 64) >> ilog2(RZONES_DESC_HD); + +- arr = kzalloc(alloc_len, GFP_ATOMIC); ++ arr = kzalloc(alloc_len, GFP_ATOMIC | __GFP_NOWARN); + if (!arr) { + mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, + INSUFF_RES_ASCQ); +@@ -7340,7 +7340,10 @@ clean: + kfree(sdbg_devinfo->zstate); + kfree(sdbg_devinfo); + } +- kfree(sdbg_host); ++ if (sdbg_host->dev.release) ++ put_device(&sdbg_host->dev); ++ else ++ kfree(sdbg_host); + pr_warn("%s: failed, errno=%d\n", __func__, -error); + return error; + } +diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c +index 6995c89792300..02520f9123066 100644 +--- a/drivers/scsi/scsi_error.c ++++ b/drivers/scsi/scsi_error.c +@@ -343,19 +343,11 @@ enum blk_eh_timer_return scsi_timeout(struct request *req) + + if (rtn == BLK_EH_DONE) { + /* +- * Set the command to complete first in order to prevent a real +- * completion from releasing the command while error handling +- * is using it. If the command was already completed, then the +- * lower level driver beat the timeout handler, and it is safe +- * to return without escalating error recovery. +- * +- * If timeout handling lost the race to a real completion, the +- * block layer may ignore that due to a fake timeout injection, +- * so return RESET_TIMER to allow error handling another shot +- * at this command. ++ * If scsi_done() has already set SCMD_STATE_COMPLETE, do not ++ * modify *scmd. + */ + if (test_and_set_bit(SCMD_STATE_COMPLETE, &scmd->state)) +- return BLK_EH_RESET_TIMER; ++ return BLK_EH_DONE; + if (scsi_abort_command(scmd) != SUCCESS) { + set_host_byte(scmd, DID_TIME_OUT); + scsi_eh_scmd_add(scmd); +diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h +index e550b12e525a1..c8235f15728bb 100644 +--- a/drivers/scsi/smartpqi/smartpqi.h ++++ b/drivers/scsi/smartpqi/smartpqi.h +@@ -1130,7 +1130,7 @@ struct pqi_scsi_dev { + u8 phy_id; + u8 ncq_prio_enable; + u8 ncq_prio_support; +- u8 multi_lun_device_lun_count; ++ u8 lun_count; + bool raid_bypass_configured; /* RAID bypass configured */ + bool raid_bypass_enabled; /* RAID bypass enabled */ + u32 next_bypass_group[RAID_MAP_MAX_DATA_DISKS_PER_ROW]; +diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c +index b971fbe3b3a17..9f0f69c1ed665 100644 +--- a/drivers/scsi/smartpqi/smartpqi_init.c ++++ b/drivers/scsi/smartpqi/smartpqi_init.c +@@ -1610,9 +1610,7 @@ static int pqi_get_physical_device_info(struct pqi_ctrl_info *ctrl_info, + &id_phys->alternate_paths_phys_connector, + sizeof(device->phys_connector)); + device->bay = id_phys->phys_bay_in_box; +- device->multi_lun_device_lun_count = id_phys->multi_lun_device_lun_count; +- if (!device->multi_lun_device_lun_count) +- device->multi_lun_device_lun_count = 1; ++ device->lun_count = id_phys->multi_lun_device_lun_count; + if ((id_phys->even_more_flags & PQI_DEVICE_PHY_MAP_SUPPORTED) && + id_phys->phy_count) + device->phy_id = +@@ -1746,7 +1744,7 @@ out: + return offline; + } + +-static int pqi_get_device_info(struct pqi_ctrl_info *ctrl_info, ++static int pqi_get_device_info_phys_logical(struct pqi_ctrl_info *ctrl_info, + struct pqi_scsi_dev *device, + struct bmic_identify_physical_device *id_phys) + { +@@ -1763,6 +1761,20 @@ static int pqi_get_device_info(struct pqi_ctrl_info *ctrl_info, + return rc; + } + ++static int pqi_get_device_info(struct pqi_ctrl_info *ctrl_info, ++ struct pqi_scsi_dev *device, ++ struct bmic_identify_physical_device *id_phys) ++{ ++ int rc; ++ ++ rc = pqi_get_device_info_phys_logical(ctrl_info, device, id_phys); ++ ++ if (rc == 0 && device->lun_count == 0) ++ device->lun_count = 1; ++ ++ return rc; ++} ++ + static void pqi_show_volume_status(struct pqi_ctrl_info *ctrl_info, + struct pqi_scsi_dev *device) + { +@@ -1897,7 +1909,7 @@ static inline void pqi_remove_device(struct pqi_ctrl_info *ctrl_info, struct pqi + int rc; + int lun; + +- for (lun = 0; lun < device->multi_lun_device_lun_count; lun++) { ++ for (lun = 0; lun < device->lun_count; lun++) { + rc = pqi_device_wait_for_pending_io(ctrl_info, device, lun, + PQI_REMOVE_DEVICE_PENDING_IO_TIMEOUT_MSECS); + if (rc) +@@ -2076,6 +2088,7 @@ static void pqi_scsi_update_device(struct pqi_ctrl_info *ctrl_info, + existing_device->sas_address = new_device->sas_address; + existing_device->queue_depth = new_device->queue_depth; + existing_device->device_offline = false; ++ existing_device->lun_count = new_device->lun_count; + + if (pqi_is_logical_device(existing_device)) { + existing_device->is_external_raid_device = new_device->is_external_raid_device; +@@ -2108,10 +2121,6 @@ static void pqi_scsi_update_device(struct pqi_ctrl_info *ctrl_info, + existing_device->phy_connected_dev_type = new_device->phy_connected_dev_type; + memcpy(existing_device->box, new_device->box, sizeof(existing_device->box)); + memcpy(existing_device->phys_connector, new_device->phys_connector, sizeof(existing_device->phys_connector)); +- +- existing_device->multi_lun_device_lun_count = new_device->multi_lun_device_lun_count; +- if (existing_device->multi_lun_device_lun_count == 0) +- existing_device->multi_lun_device_lun_count = 1; + } + } + +@@ -6484,6 +6493,12 @@ static void pqi_slave_destroy(struct scsi_device *sdev) + return; + } + ++ device->lun_count--; ++ if (device->lun_count > 0) { ++ mutex_unlock(&ctrl_info->scan_mutex); ++ return; ++ } ++ + spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); + list_del(&device->scsi_device_list_entry); + spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); +@@ -9302,6 +9317,10 @@ static const struct pci_device_id pqi_pci_id_table[] = { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x193d, 0x1109) + }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ 0x193d, 0x110b) ++ }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x193d, 0x8460) +@@ -9402,6 +9421,22 @@ static const struct pci_device_id pqi_pci_id_table[] = { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x0072) + }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ 0x1bd4, 0x0086) ++ }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ 0x1bd4, 0x0087) ++ }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ 0x1bd4, 0x0088) ++ }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ 0x1bd4, 0x0089) ++ }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x19e5, 0xd227) +@@ -9650,6 +9685,10 @@ static const struct pci_device_id pqi_pci_id_table[] = { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_ADAPTEC2, 0x1474) + }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ PCI_VENDOR_ID_ADAPTEC2, 0x1475) ++ }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_ADAPTEC2, 0x1480) +@@ -9706,6 +9745,14 @@ static const struct pci_device_id pqi_pci_id_table[] = { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_ADAPTEC2, 0x14c2) + }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ PCI_VENDOR_ID_ADAPTEC2, 0x14c3) ++ }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ PCI_VENDOR_ID_ADAPTEC2, 0x14c4) ++ }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_ADAPTEC2, 0x14d0) +@@ -9942,6 +9989,18 @@ static const struct pci_device_id pqi_pci_id_table[] = { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_LENOVO, 0x0623) + }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ 0x1e93, 0x1000) ++ }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ 0x1e93, 0x1001) ++ }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ 0x1e93, 0x1002) ++ }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_ANY_ID, PCI_ANY_ID) +diff --git a/drivers/scsi/snic/snic_disc.c b/drivers/scsi/snic/snic_disc.c +index 9b2b5f8c23b9a..8fbf3c1b1311d 100644 +--- a/drivers/scsi/snic/snic_disc.c ++++ b/drivers/scsi/snic/snic_disc.c +@@ -304,6 +304,9 @@ snic_tgt_create(struct snic *snic, struct snic_tgt_id *tgtid) + ret); + + put_device(&snic->shost->shost_gendev); ++ spin_lock_irqsave(snic->shost->host_lock, flags); ++ list_del(&tgt->list); ++ spin_unlock_irqrestore(snic->shost->host_lock, flags); + kfree(tgt); + tgt = NULL; + +diff --git a/drivers/soc/apple/rtkit.c b/drivers/soc/apple/rtkit.c +index 031ec4aa06d55..8ec74d7539eb4 100644 +--- a/drivers/soc/apple/rtkit.c ++++ b/drivers/soc/apple/rtkit.c +@@ -926,8 +926,10 @@ int apple_rtkit_wake(struct apple_rtkit *rtk) + } + EXPORT_SYMBOL_GPL(apple_rtkit_wake); + +-static void apple_rtkit_free(struct apple_rtkit *rtk) ++static void apple_rtkit_free(void *data) + { ++ struct apple_rtkit *rtk = data; ++ + mbox_free_channel(rtk->mbox_chan); + destroy_workqueue(rtk->wq); + +@@ -950,8 +952,7 @@ struct apple_rtkit *devm_apple_rtkit_init(struct device *dev, void *cookie, + if (IS_ERR(rtk)) + return rtk; + +- ret = devm_add_action_or_reset(dev, (void (*)(void *))apple_rtkit_free, +- rtk); ++ ret = devm_add_action_or_reset(dev, apple_rtkit_free, rtk); + if (ret) + return ERR_PTR(ret); + +diff --git a/drivers/soc/apple/sart.c b/drivers/soc/apple/sart.c +index 83804b16ad03d..afa1117368997 100644 +--- a/drivers/soc/apple/sart.c ++++ b/drivers/soc/apple/sart.c +@@ -164,6 +164,11 @@ static int apple_sart_probe(struct platform_device *pdev) + return 0; + } + ++static void apple_sart_put_device(void *dev) ++{ ++ put_device(dev); ++} ++ + struct apple_sart *devm_apple_sart_get(struct device *dev) + { + struct device_node *sart_node; +@@ -187,7 +192,7 @@ struct apple_sart *devm_apple_sart_get(struct device *dev) + return ERR_PTR(-EPROBE_DEFER); + } + +- ret = devm_add_action_or_reset(dev, (void (*)(void *))put_device, ++ ret = devm_add_action_or_reset(dev, apple_sart_put_device, + &sart_pdev->dev); + if (ret) + return ERR_PTR(ret); +diff --git a/drivers/soc/mediatek/mtk-pm-domains.c b/drivers/soc/mediatek/mtk-pm-domains.c +index 09e3c38b84664..474b272f9b02d 100644 +--- a/drivers/soc/mediatek/mtk-pm-domains.c ++++ b/drivers/soc/mediatek/mtk-pm-domains.c +@@ -275,9 +275,9 @@ static int scpsys_power_off(struct generic_pm_domain *genpd) + clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks); + + /* subsys power off */ +- regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT); + regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT); + regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT); ++ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT); + regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT); + regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT); + +diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c +index b4046f393575e..cd44f17dad3d0 100644 +--- a/drivers/soc/qcom/apr.c ++++ b/drivers/soc/qcom/apr.c +@@ -454,11 +454,19 @@ static int apr_add_device(struct device *dev, struct device_node *np, + adev->dev.driver = NULL; + + spin_lock(&apr->svcs_lock); +- idr_alloc(&apr->svcs_idr, svc, svc_id, svc_id + 1, GFP_ATOMIC); ++ ret = idr_alloc(&apr->svcs_idr, svc, svc_id, svc_id + 1, GFP_ATOMIC); + spin_unlock(&apr->svcs_lock); ++ if (ret < 0) { ++ dev_err(dev, "idr_alloc failed: %d\n", ret); ++ goto out; ++ } + +- of_property_read_string_index(np, "qcom,protection-domain", +- 1, &adev->service_path); ++ ret = of_property_read_string_index(np, "qcom,protection-domain", ++ 1, &adev->service_path); ++ if (ret < 0) { ++ dev_err(dev, "Failed to read second value of qcom,protection-domain\n"); ++ goto out; ++ } + + dev_info(dev, "Adding APR/GPR dev: %s\n", dev_name(&adev->dev)); + +@@ -468,6 +476,7 @@ static int apr_add_device(struct device *dev, struct device_node *np, + put_device(&adev->dev); + } + ++out: + return ret; + } + +diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c +index 8b7e8118f3cec..82c3cfdcc5601 100644 +--- a/drivers/soc/qcom/llcc-qcom.c ++++ b/drivers/soc/qcom/llcc-qcom.c +@@ -849,7 +849,7 @@ static int qcom_llcc_probe(struct platform_device *pdev) + if (ret) + goto err; + +- drv_data->ecc_irq = platform_get_irq(pdev, 0); ++ drv_data->ecc_irq = platform_get_irq_optional(pdev, 0); + if (drv_data->ecc_irq >= 0) { + llcc_edac = platform_device_register_data(&pdev->dev, + "qcom_llcc_edac", -1, drv_data, +diff --git a/drivers/soc/sifive/sifive_ccache.c b/drivers/soc/sifive/sifive_ccache.c +index 1c171150e878d..3684f5b40a80e 100644 +--- a/drivers/soc/sifive/sifive_ccache.c ++++ b/drivers/soc/sifive/sifive_ccache.c +@@ -215,20 +215,27 @@ static int __init sifive_ccache_init(void) + if (!np) + return -ENODEV; + +- if (of_address_to_resource(np, 0, &res)) +- return -ENODEV; ++ if (of_address_to_resource(np, 0, &res)) { ++ rc = -ENODEV; ++ goto err_node_put; ++ } + + ccache_base = ioremap(res.start, resource_size(&res)); +- if (!ccache_base) +- return -ENOMEM; ++ if (!ccache_base) { ++ rc = -ENOMEM; ++ goto err_node_put; ++ } + +- if (of_property_read_u32(np, "cache-level", &level)) +- return -ENOENT; ++ if (of_property_read_u32(np, "cache-level", &level)) { ++ rc = -ENOENT; ++ goto err_unmap; ++ } + + intr_num = of_property_count_u32_elems(np, "interrupts"); + if (!intr_num) { + pr_err("No interrupts property\n"); +- return -ENODEV; ++ rc = -ENODEV; ++ goto err_unmap; + } + + for (i = 0; i < intr_num; i++) { +@@ -237,9 +244,10 @@ static int __init sifive_ccache_init(void) + NULL); + if (rc) { + pr_err("Could not request IRQ %d\n", g_irq[i]); +- return rc; ++ goto err_free_irq; + } + } ++ of_node_put(np); + + ccache_config_read(); + +@@ -250,6 +258,15 @@ static int __init sifive_ccache_init(void) + setup_sifive_debug(); + #endif + return 0; ++ ++err_free_irq: ++ while (--i >= 0) ++ free_irq(g_irq[i], NULL); ++err_unmap: ++ iounmap(ccache_base); ++err_node_put: ++ of_node_put(np); ++ return rc; + } + + device_initcall(sifive_ccache_init); +diff --git a/drivers/soc/tegra/cbb/tegra194-cbb.c b/drivers/soc/tegra/cbb/tegra194-cbb.c +index 1ae0bd9a1ac1b..2e952c6f7c9e3 100644 +--- a/drivers/soc/tegra/cbb/tegra194-cbb.c ++++ b/drivers/soc/tegra/cbb/tegra194-cbb.c +@@ -102,8 +102,6 @@ + #define CLUSTER_NOC_VQC GENMASK(17, 16) + #define CLUSTER_NOC_MSTR_ID GENMASK(21, 18) + +-#define USRBITS_MSTR_ID GENMASK(21, 18) +- + #define CBB_ERR_OPC GENMASK(4, 1) + #define CBB_ERR_ERRCODE GENMASK(10, 8) + #define CBB_ERR_LEN1 GENMASK(27, 16) +@@ -2038,15 +2036,17 @@ static irqreturn_t tegra194_cbb_err_isr(int irq, void *data) + smp_processor_id(), priv->noc->name, priv->res->start, + irq); + +- mstr_id = FIELD_GET(USRBITS_MSTR_ID, priv->errlog5) - 1; + is_fatal = print_errlog(NULL, priv, status); + + /* +- * If illegal request is from CCPLEX(0x1) +- * initiator then call BUG() to crash system. ++ * If illegal request is from CCPLEX(0x1) initiator ++ * and error is fatal then call BUG() to crash system. + */ +- if ((mstr_id == 0x1) && priv->noc->erd_mask_inband_err) +- is_inband_err = 1; ++ if (priv->noc->erd_mask_inband_err) { ++ mstr_id = FIELD_GET(CBB_NOC_MSTR_ID, priv->errlog5); ++ if (mstr_id == 0x1) ++ is_inband_err = 1; ++ } + } + } + +diff --git a/drivers/soc/tegra/cbb/tegra234-cbb.c b/drivers/soc/tegra/cbb/tegra234-cbb.c +index 3528f9e15d5c0..f33d094e5ea60 100644 +--- a/drivers/soc/tegra/cbb/tegra234-cbb.c ++++ b/drivers/soc/tegra/cbb/tegra234-cbb.c +@@ -72,6 +72,11 @@ + + #define REQ_SOCKET_ID GENMASK(27, 24) + ++#define CCPLEX_MSTRID 0x1 ++#define FIREWALL_APERTURE_SZ 0x10000 ++/* Write firewall check enable */ ++#define WEN 0x20000 ++ + enum tegra234_cbb_fabric_ids { + CBB_FAB_ID, + SCE_FAB_ID, +@@ -92,11 +97,15 @@ struct tegra234_slave_lookup { + struct tegra234_cbb_fabric { + const char *name; + phys_addr_t off_mask_erd; +- bool erd_mask_inband_err; ++ phys_addr_t firewall_base; ++ unsigned int firewall_ctl; ++ unsigned int firewall_wr_ctl; + const char * const *master_id; + unsigned int notifier_offset; + const struct tegra_cbb_error *errors; ++ const int max_errors; + const struct tegra234_slave_lookup *slave_map; ++ const int max_slaves; + }; + + struct tegra234_cbb { +@@ -128,6 +137,44 @@ static inline struct tegra234_cbb *to_tegra234_cbb(struct tegra_cbb *cbb) + static LIST_HEAD(cbb_list); + static DEFINE_SPINLOCK(cbb_lock); + ++static bool ++tegra234_cbb_write_access_allowed(struct platform_device *pdev, struct tegra234_cbb *cbb) ++{ ++ u32 val; ++ ++ if (!cbb->fabric->firewall_base || ++ !cbb->fabric->firewall_ctl || ++ !cbb->fabric->firewall_wr_ctl) { ++ dev_info(&pdev->dev, "SoC data missing for firewall\n"); ++ return false; ++ } ++ ++ if ((cbb->fabric->firewall_ctl > FIREWALL_APERTURE_SZ) || ++ (cbb->fabric->firewall_wr_ctl > FIREWALL_APERTURE_SZ)) { ++ dev_err(&pdev->dev, "wrong firewall offset value\n"); ++ return false; ++ } ++ ++ val = readl(cbb->regs + cbb->fabric->firewall_base + cbb->fabric->firewall_ctl); ++ /* ++ * If the firewall check feature for allowing or blocking the ++ * write accesses through the firewall of a fabric is disabled ++ * then CCPLEX can write to the registers of that fabric. ++ */ ++ if (!(val & WEN)) ++ return true; ++ ++ /* ++ * If the firewall check is enabled then check whether CCPLEX ++ * has write access to the fabric's error notifier registers ++ */ ++ val = readl(cbb->regs + cbb->fabric->firewall_base + cbb->fabric->firewall_wr_ctl); ++ if (val & (BIT(CCPLEX_MSTRID))) ++ return true; ++ ++ return false; ++} ++ + static void tegra234_cbb_fault_enable(struct tegra_cbb *cbb) + { + struct tegra234_cbb *priv = to_tegra234_cbb(cbb); +@@ -271,6 +318,12 @@ static void tegra234_cbb_print_error(struct seq_file *file, struct tegra234_cbb + tegra_cbb_print_err(file, "\t Multiple type of errors reported\n"); + + while (status) { ++ if (type >= cbb->fabric->max_errors) { ++ tegra_cbb_print_err(file, "\t Wrong type index:%u, status:%u\n", ++ type, status); ++ return; ++ } ++ + if (status & 0x1) + tegra_cbb_print_err(file, "\t Error Code\t\t: %s\n", + cbb->fabric->errors[type].code); +@@ -282,6 +335,12 @@ static void tegra234_cbb_print_error(struct seq_file *file, struct tegra234_cbb + type = 0; + + while (overflow) { ++ if (type >= cbb->fabric->max_errors) { ++ tegra_cbb_print_err(file, "\t Wrong type index:%u, overflow:%u\n", ++ type, overflow); ++ return; ++ } ++ + if (overflow & 0x1) + tegra_cbb_print_err(file, "\t Overflow\t\t: Multiple %s\n", + cbb->fabric->errors[type].code); +@@ -334,8 +393,11 @@ static void print_errlog_err(struct seq_file *file, struct tegra234_cbb *cbb) + access_type = FIELD_GET(FAB_EM_EL_ACCESSTYPE, cbb->mn_attr0); + + tegra_cbb_print_err(file, "\n"); +- tegra_cbb_print_err(file, "\t Error Code\t\t: %s\n", +- cbb->fabric->errors[cbb->type].code); ++ if (cbb->type < cbb->fabric->max_errors) ++ tegra_cbb_print_err(file, "\t Error Code\t\t: %s\n", ++ cbb->fabric->errors[cbb->type].code); ++ else ++ tegra_cbb_print_err(file, "\t Wrong type index:%u\n", cbb->type); + + tegra_cbb_print_err(file, "\t MASTER_ID\t\t: %s\n", cbb->fabric->master_id[mstr_id]); + tegra_cbb_print_err(file, "\t Address\t\t: %#llx\n", cbb->access); +@@ -374,6 +436,11 @@ static void print_errlog_err(struct seq_file *file, struct tegra234_cbb *cbb) + if ((fab_id == PSC_FAB_ID) || (fab_id == FSI_FAB_ID)) + return; + ++ if (slave_id >= cbb->fabric->max_slaves) { ++ tegra_cbb_print_err(file, "\t Invalid slave_id:%d\n", slave_id); ++ return; ++ } ++ + if (!strcmp(cbb->fabric->errors[cbb->type].code, "TIMEOUT_ERR")) { + tegra234_lookup_slave_timeout(file, cbb, slave_id, fab_id); + return; +@@ -517,7 +584,7 @@ static irqreturn_t tegra234_cbb_isr(int irq, void *data) + u32 status = tegra_cbb_get_status(cbb); + + if (status && (irq == priv->sec_irq)) { +- tegra_cbb_print_err(NULL, "CPU:%d, Error: %s@%llx, irq=%d\n", ++ tegra_cbb_print_err(NULL, "CPU:%d, Error: %s@0x%llx, irq=%d\n", + smp_processor_id(), priv->fabric->name, + priv->res->start, irq); + +@@ -525,14 +592,14 @@ static irqreturn_t tegra234_cbb_isr(int irq, void *data) + if (err) + goto unlock; + +- mstr_id = FIELD_GET(USRBITS_MSTR_ID, priv->mn_user_bits); +- + /* +- * If illegal request is from CCPLEX(id:0x1) master then call BUG() to +- * crash system. ++ * If illegal request is from CCPLEX(id:0x1) master then call WARN() + */ +- if ((mstr_id == 0x1) && priv->fabric->off_mask_erd) +- is_inband_err = 1; ++ if (priv->fabric->off_mask_erd) { ++ mstr_id = FIELD_GET(USRBITS_MSTR_ID, priv->mn_user_bits); ++ if (mstr_id == CCPLEX_MSTRID) ++ is_inband_err = 1; ++ } + } + } + +@@ -640,8 +707,13 @@ static const struct tegra234_cbb_fabric tegra234_aon_fabric = { + .name = "aon-fabric", + .master_id = tegra234_master_id, + .slave_map = tegra234_aon_slave_map, ++ .max_slaves = ARRAY_SIZE(tegra234_aon_slave_map), + .errors = tegra234_cbb_errors, ++ .max_errors = ARRAY_SIZE(tegra234_cbb_errors), + .notifier_offset = 0x17000, ++ .firewall_base = 0x30000, ++ .firewall_ctl = 0x8d0, ++ .firewall_wr_ctl = 0x8c8, + }; + + static const struct tegra234_slave_lookup tegra234_bpmp_slave_map[] = { +@@ -656,8 +728,13 @@ static const struct tegra234_cbb_fabric tegra234_bpmp_fabric = { + .name = "bpmp-fabric", + .master_id = tegra234_master_id, + .slave_map = tegra234_bpmp_slave_map, ++ .max_slaves = ARRAY_SIZE(tegra234_bpmp_slave_map), + .errors = tegra234_cbb_errors, ++ .max_errors = ARRAY_SIZE(tegra234_cbb_errors), + .notifier_offset = 0x19000, ++ .firewall_base = 0x30000, ++ .firewall_ctl = 0x8f0, ++ .firewall_wr_ctl = 0x8e8, + }; + + static const struct tegra234_slave_lookup tegra234_cbb_slave_map[] = { +@@ -728,55 +805,62 @@ static const struct tegra234_cbb_fabric tegra234_cbb_fabric = { + .name = "cbb-fabric", + .master_id = tegra234_master_id, + .slave_map = tegra234_cbb_slave_map, ++ .max_slaves = ARRAY_SIZE(tegra234_cbb_slave_map), + .errors = tegra234_cbb_errors, ++ .max_errors = ARRAY_SIZE(tegra234_cbb_errors), + .notifier_offset = 0x60000, +- .off_mask_erd = 0x3a004 ++ .off_mask_erd = 0x3a004, ++ .firewall_base = 0x10000, ++ .firewall_ctl = 0x23f0, ++ .firewall_wr_ctl = 0x23e8, + }; + +-static const struct tegra234_slave_lookup tegra234_dce_slave_map[] = { ++static const struct tegra234_slave_lookup tegra234_common_slave_map[] = { + { "AXI2APB", 0x00000 }, + { "AST0", 0x15000 }, + { "AST1", 0x16000 }, ++ { "CBB", 0x17000 }, ++ { "RSVD", 0x00000 }, + { "CPU", 0x18000 }, + }; + + static const struct tegra234_cbb_fabric tegra234_dce_fabric = { + .name = "dce-fabric", + .master_id = tegra234_master_id, +- .slave_map = tegra234_dce_slave_map, ++ .slave_map = tegra234_common_slave_map, ++ .max_slaves = ARRAY_SIZE(tegra234_common_slave_map), + .errors = tegra234_cbb_errors, ++ .max_errors = ARRAY_SIZE(tegra234_cbb_errors), + .notifier_offset = 0x19000, +-}; +- +-static const struct tegra234_slave_lookup tegra234_rce_slave_map[] = { +- { "AXI2APB", 0x00000 }, +- { "AST0", 0x15000 }, +- { "AST1", 0x16000 }, +- { "CPU", 0x18000 }, ++ .firewall_base = 0x30000, ++ .firewall_ctl = 0x290, ++ .firewall_wr_ctl = 0x288, + }; + + static const struct tegra234_cbb_fabric tegra234_rce_fabric = { + .name = "rce-fabric", + .master_id = tegra234_master_id, +- .slave_map = tegra234_rce_slave_map, ++ .slave_map = tegra234_common_slave_map, ++ .max_slaves = ARRAY_SIZE(tegra234_common_slave_map), + .errors = tegra234_cbb_errors, ++ .max_errors = ARRAY_SIZE(tegra234_cbb_errors), + .notifier_offset = 0x19000, +-}; +- +-static const struct tegra234_slave_lookup tegra234_sce_slave_map[] = { +- { "AXI2APB", 0x00000 }, +- { "AST0", 0x15000 }, +- { "AST1", 0x16000 }, +- { "CBB", 0x17000 }, +- { "CPU", 0x18000 }, ++ .firewall_base = 0x30000, ++ .firewall_ctl = 0x290, ++ .firewall_wr_ctl = 0x288, + }; + + static const struct tegra234_cbb_fabric tegra234_sce_fabric = { + .name = "sce-fabric", + .master_id = tegra234_master_id, +- .slave_map = tegra234_sce_slave_map, ++ .slave_map = tegra234_common_slave_map, ++ .max_slaves = ARRAY_SIZE(tegra234_common_slave_map), + .errors = tegra234_cbb_errors, ++ .max_errors = ARRAY_SIZE(tegra234_cbb_errors), + .notifier_offset = 0x19000, ++ .firewall_base = 0x30000, ++ .firewall_ctl = 0x290, ++ .firewall_wr_ctl = 0x288, + }; + + static const char * const tegra241_master_id[] = { +@@ -889,7 +973,7 @@ static const struct tegra_cbb_error tegra241_cbb_errors[] = { + }; + + static const struct tegra234_slave_lookup tegra241_cbb_slave_map[] = { +- { "CCPLEX", 0x50000 }, ++ { "RSVD", 0x00000 }, + { "PCIE_C8", 0x51000 }, + { "PCIE_C9", 0x52000 }, + { "RSVD", 0x00000 }, +@@ -942,20 +1026,30 @@ static const struct tegra234_slave_lookup tegra241_cbb_slave_map[] = { + { "PCIE_C3", 0x58000 }, + { "PCIE_C0", 0x59000 }, + { "PCIE_C1", 0x5a000 }, ++ { "CCPLEX", 0x50000 }, + { "AXI2APB_29", 0x85000 }, + { "AXI2APB_30", 0x86000 }, ++ { "CBB_CENTRAL", 0x00000 }, ++ { "AXI2APB_31", 0x8E000 }, ++ { "AXI2APB_32", 0x8F000 }, + }; + + static const struct tegra234_cbb_fabric tegra241_cbb_fabric = { + .name = "cbb-fabric", + .master_id = tegra241_master_id, + .slave_map = tegra241_cbb_slave_map, ++ .max_slaves = ARRAY_SIZE(tegra241_cbb_slave_map), + .errors = tegra241_cbb_errors, ++ .max_errors = ARRAY_SIZE(tegra241_cbb_errors), + .notifier_offset = 0x60000, + .off_mask_erd = 0x40004, ++ .firewall_base = 0x20000, ++ .firewall_ctl = 0x2370, ++ .firewall_wr_ctl = 0x2368, + }; + + static const struct tegra234_slave_lookup tegra241_bpmp_slave_map[] = { ++ { "RSVD", 0x00000 }, + { "RSVD", 0x00000 }, + { "RSVD", 0x00000 }, + { "CBB", 0x15000 }, +@@ -969,8 +1063,13 @@ static const struct tegra234_cbb_fabric tegra241_bpmp_fabric = { + .name = "bpmp-fabric", + .master_id = tegra241_master_id, + .slave_map = tegra241_bpmp_slave_map, ++ .max_slaves = ARRAY_SIZE(tegra241_bpmp_slave_map), + .errors = tegra241_cbb_errors, ++ .max_errors = ARRAY_SIZE(tegra241_cbb_errors), + .notifier_offset = 0x19000, ++ .firewall_base = 0x30000, ++ .firewall_ctl = 0x8f0, ++ .firewall_wr_ctl = 0x8e8, + }; + + static const struct of_device_id tegra234_cbb_dt_ids[] = { +@@ -1055,6 +1154,15 @@ static int tegra234_cbb_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, cbb); + ++ /* ++ * Don't enable error reporting for a Fabric if write to it's registers ++ * is blocked by CBB firewall. ++ */ ++ if (!tegra234_cbb_write_access_allowed(pdev, cbb)) { ++ dev_info(&pdev->dev, "error reporting not enabled due to firewall\n"); ++ return 0; ++ } ++ + spin_lock_irqsave(&cbb_lock, flags); + list_add(&cbb->base.node, &cbb_list); + spin_unlock_irqrestore(&cbb_lock, flags); +diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c +index 92af7d1b6f5bd..8fb76908be704 100644 +--- a/drivers/soc/ti/knav_qmss_queue.c ++++ b/drivers/soc/ti/knav_qmss_queue.c +@@ -67,7 +67,7 @@ static DEFINE_MUTEX(knav_dev_lock); + * Newest followed by older ones. Search is done from start of the array + * until a firmware file is found. + */ +-const char *knav_acc_firmwares[] = {"ks2_qmss_pdsp_acc48.bin"}; ++static const char * const knav_acc_firmwares[] = {"ks2_qmss_pdsp_acc48.bin"}; + + static bool device_ready; + bool knav_qmss_device_ready(void) +@@ -1785,6 +1785,7 @@ static int knav_queue_probe(struct platform_device *pdev) + pm_runtime_enable(&pdev->dev); + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret < 0) { ++ pm_runtime_disable(&pdev->dev); + dev_err(dev, "Failed to enable QMSS\n"); + return ret; + } +diff --git a/drivers/soc/ti/smartreflex.c b/drivers/soc/ti/smartreflex.c +index ad2bb72e640c8..6a389a6444f36 100644 +--- a/drivers/soc/ti/smartreflex.c ++++ b/drivers/soc/ti/smartreflex.c +@@ -932,6 +932,7 @@ static int omap_sr_probe(struct platform_device *pdev) + err_debugfs: + debugfs_remove_recursive(sr_info->dbg_dir); + err_list_del: ++ pm_runtime_disable(&pdev->dev); + list_del(&sr_info->node); + clk_unprepare(sr_info->fck); + +diff --git a/drivers/soundwire/dmi-quirks.c b/drivers/soundwire/dmi-quirks.c +index f81cdd83ec26e..7969881f126dc 100644 +--- a/drivers/soundwire/dmi-quirks.c ++++ b/drivers/soundwire/dmi-quirks.c +@@ -90,6 +90,14 @@ static const struct dmi_system_id adr_remap_quirk_table[] = { + }, + .driver_data = (void *)intel_tgl_bios, + }, ++ { ++ /* quirk used for NUC15 LAPBC710 skew */ ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), ++ DMI_MATCH(DMI_BOARD_NAME, "LAPBC710"), ++ }, ++ .driver_data = (void *)intel_tgl_bios, ++ }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), +diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c +index 731624f157fc0..93152144fd2ec 100644 +--- a/drivers/spi/spi-fsl-spi.c ++++ b/drivers/spi/spi-fsl-spi.c +@@ -333,13 +333,26 @@ static int fsl_spi_prepare_message(struct spi_controller *ctlr, + { + struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(ctlr); + struct spi_transfer *t; ++ struct spi_transfer *first; ++ ++ first = list_first_entry(&m->transfers, struct spi_transfer, ++ transfer_list); + + /* + * In CPU mode, optimize large byte transfers to use larger + * bits_per_word values to reduce number of interrupts taken. ++ * ++ * Some glitches can appear on the SPI clock when the mode changes. ++ * Check that there is no speed change during the transfer and set it up ++ * now to change the mode without having a chip-select asserted. + */ +- if (!(mpc8xxx_spi->flags & SPI_CPM_MODE)) { +- list_for_each_entry(t, &m->transfers, transfer_list) { ++ list_for_each_entry(t, &m->transfers, transfer_list) { ++ if (t->speed_hz != first->speed_hz) { ++ dev_err(&m->spi->dev, ++ "speed_hz cannot change during message.\n"); ++ return -EINVAL; ++ } ++ if (!(mpc8xxx_spi->flags & SPI_CPM_MODE)) { + if (t->len < 256 || t->bits_per_word != 8) + continue; + if ((t->len & 3) == 0) +@@ -348,7 +361,7 @@ static int fsl_spi_prepare_message(struct spi_controller *ctlr, + t->bits_per_word = 16; + } + } +- return 0; ++ return fsl_spi_setup_transfer(m->spi, first); + } + + static int fsl_spi_transfer_one(struct spi_controller *controller, +diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c +index 4b12c4964a664..9c8c7948044ed 100644 +--- a/drivers/spi/spi-gpio.c ++++ b/drivers/spi/spi-gpio.c +@@ -268,9 +268,19 @@ static int spi_gpio_set_direction(struct spi_device *spi, bool output) + if (output) + return gpiod_direction_output(spi_gpio->mosi, 1); + +- ret = gpiod_direction_input(spi_gpio->mosi); +- if (ret) +- return ret; ++ /* ++ * Only change MOSI to an input if using 3WIRE mode. ++ * Otherwise, MOSI could be left floating if there is ++ * no pull resistor connected to the I/O pin, or could ++ * be left logic high if there is a pull-up. Transmitting ++ * logic high when only clocking MISO data in can put some ++ * SPI devices in to a bad state. ++ */ ++ if (spi->mode & SPI_3WIRE) { ++ ret = gpiod_direction_input(spi_gpio->mosi); ++ if (ret) ++ return ret; ++ } + /* + * Send a turnaround high impedance cycle when switching + * from output to input. Theoretically there should be +diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c +index b2775d82d2d7b..6313e7d0cdf87 100644 +--- a/drivers/spi/spidev.c ++++ b/drivers/spi/spidev.c +@@ -377,12 +377,23 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + switch (cmd) { + /* read requests */ + case SPI_IOC_RD_MODE: +- retval = put_user(spi->mode & SPI_MODE_MASK, +- (__u8 __user *)arg); +- break; + case SPI_IOC_RD_MODE32: +- retval = put_user(spi->mode & SPI_MODE_MASK, +- (__u32 __user *)arg); ++ tmp = spi->mode; ++ ++ { ++ struct spi_controller *ctlr = spi->controller; ++ ++ if (ctlr->use_gpio_descriptors && ctlr->cs_gpiods && ++ ctlr->cs_gpiods[spi->chip_select]) ++ tmp &= ~SPI_CS_HIGH; ++ } ++ ++ if (cmd == SPI_IOC_RD_MODE) ++ retval = put_user(tmp & SPI_MODE_MASK, ++ (__u8 __user *)arg); ++ else ++ retval = put_user(tmp & SPI_MODE_MASK, ++ (__u32 __user *)arg); + break; + case SPI_IOC_RD_LSB_FIRST: + retval = put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0, +diff --git a/drivers/staging/media/deprecated/stkwebcam/Kconfig b/drivers/staging/media/deprecated/stkwebcam/Kconfig +index 4450403dff41f..7234498e634ac 100644 +--- a/drivers/staging/media/deprecated/stkwebcam/Kconfig ++++ b/drivers/staging/media/deprecated/stkwebcam/Kconfig +@@ -2,7 +2,7 @@ + config VIDEO_STKWEBCAM + tristate "USB Syntek DC1125 Camera support (DEPRECATED)" + depends on VIDEO_DEV +- depends on USB ++ depends on MEDIA_USB_SUPPORT && MEDIA_CAMERA_SUPPORT + help + Say Y here if you want to use this type of camera. + Supported devices are typically found in some Asus laptops, +diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c +index e5b550ccfa22d..c77401f184d74 100644 +--- a/drivers/staging/media/imx/imx7-media-csi.c ++++ b/drivers/staging/media/imx/imx7-media-csi.c +@@ -521,9 +521,9 @@ static void imx7_csi_configure(struct imx7_csi *csi) + cr18 = imx7_csi_reg_read(csi, CSI_CSICR18); + + cr18 &= ~(BIT_CSI_HW_ENABLE | BIT_MIPI_DATA_FORMAT_MASK | +- BIT_DATA_FROM_MIPI | BIT_BASEADDR_CHG_ERR_EN | +- BIT_BASEADDR_SWITCH_EN | BIT_BASEADDR_SWITCH_SEL | +- BIT_DEINTERLACE_EN); ++ BIT_DATA_FROM_MIPI | BIT_MIPI_DOUBLE_CMPNT | ++ BIT_BASEADDR_CHG_ERR_EN | BIT_BASEADDR_SWITCH_SEL | ++ BIT_BASEADDR_SWITCH_EN | BIT_DEINTERLACE_EN); + + if (out_pix->field == V4L2_FIELD_INTERLACED) { + cr18 |= BIT_DEINTERLACE_EN; +diff --git a/drivers/staging/media/rkvdec/rkvdec-vp9.c b/drivers/staging/media/rkvdec/rkvdec-vp9.c +index d8c1c0db15c70..cfae99b40ccb4 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-vp9.c ++++ b/drivers/staging/media/rkvdec/rkvdec-vp9.c +@@ -84,6 +84,8 @@ struct rkvdec_vp9_probs { + struct rkvdec_vp9_inter_frame_probs inter; + struct rkvdec_vp9_intra_only_frame_probs intra_only; + }; ++ /* 128 bit alignment */ ++ u8 padding1[11]; + }; + + /* Data structure describing auxiliary buffer format. */ +@@ -1006,6 +1008,7 @@ static int rkvdec_vp9_start(struct rkvdec_ctx *ctx) + + ctx->priv = vp9_ctx; + ++ BUILD_BUG_ON(sizeof(priv_tbl->probs) % 16); /* ensure probs size is 128-bit aligned */ + priv_tbl = dma_alloc_coherent(rkvdec->dev, sizeof(*priv_tbl), + &vp9_ctx->priv_tbl.dma, GFP_KERNEL); + if (!priv_tbl) { +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +index 4952fc17f3e6d..625f77a8c5bde 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -242,6 +242,18 @@ static void cedrus_h265_skip_bits(struct cedrus_dev *dev, int num) + } + } + ++static u32 cedrus_h265_show_bits(struct cedrus_dev *dev, int num) ++{ ++ cedrus_write(dev, VE_DEC_H265_TRIGGER, ++ VE_DEC_H265_TRIGGER_SHOW_BITS | ++ VE_DEC_H265_TRIGGER_TYPE_N_BITS(num)); ++ ++ cedrus_wait_for(dev, VE_DEC_H265_STATUS, ++ VE_DEC_H265_STATUS_VLD_BUSY); ++ ++ return cedrus_read(dev, VE_DEC_H265_BITS_READ); ++} ++ + static void cedrus_h265_write_scaling_list(struct cedrus_ctx *ctx, + struct cedrus_run *run) + { +@@ -406,7 +418,7 @@ static int cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) + u32 num_entry_point_offsets; + u32 output_pic_list_index; + u32 pic_order_cnt[2]; +- u8 *padding; ++ u8 padding; + int count; + u32 reg; + +@@ -520,21 +532,22 @@ static int cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) + if (slice_params->data_byte_offset == 0) + return -EOPNOTSUPP; + +- padding = (u8 *)vb2_plane_vaddr(&run->src->vb2_buf, 0) + +- slice_params->data_byte_offset - 1; ++ cedrus_h265_skip_bits(dev, (slice_params->data_byte_offset - 1) * 8); ++ ++ padding = cedrus_h265_show_bits(dev, 8); + + /* at least one bit must be set in that byte */ +- if (*padding == 0) ++ if (padding == 0) + return -EINVAL; + + for (count = 0; count < 8; count++) +- if (*padding & (1 << count)) ++ if (padding & (1 << count)) + break; + + /* Include the one bit. */ + count++; + +- cedrus_h265_skip_bits(dev, slice_params->data_byte_offset * 8 - count); ++ cedrus_h265_skip_bits(dev, 8 - count); + + /* Bitstream parameters. */ + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +index d81f7513ade0d..655c05b389cf5 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +@@ -505,6 +505,8 @@ + #define VE_DEC_H265_LOW_ADDR_ENTRY_POINTS_BUF(a) \ + SHIFT_AND_MASK_BITS(a, 7, 0) + ++#define VE_DEC_H265_BITS_READ (VE_ENGINE_DEC_H265 + 0xdc) ++ + #define VE_DEC_H265_SRAM_OFFSET (VE_ENGINE_DEC_H265 + 0xe0) + + #define VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L0 0x00 +diff --git a/drivers/staging/r8188eu/core/rtw_led.c b/drivers/staging/r8188eu/core/rtw_led.c +index 1e316e6358ea2..48c5db69929c3 100644 +--- a/drivers/staging/r8188eu/core/rtw_led.c ++++ b/drivers/staging/r8188eu/core/rtw_led.c +@@ -32,40 +32,19 @@ static void ResetLedStatus(struct led_priv *pLed) + + static void SwLedOn(struct adapter *padapter, struct led_priv *pLed) + { +- u8 LedCfg; +- int res; +- + if (padapter->bDriverStopped) + return; + +- res = rtw_read8(padapter, REG_LEDCFG2, &LedCfg); +- if (res) +- return; +- +- rtw_write8(padapter, REG_LEDCFG2, (LedCfg & 0xf0) | BIT(5) | BIT(6)); /* SW control led0 on. */ ++ rtw_write8(padapter, REG_LEDCFG2, BIT(5)); /* SW control led0 on. */ + pLed->bLedOn = true; + } + + static void SwLedOff(struct adapter *padapter, struct led_priv *pLed) + { +- u8 LedCfg; +- int res; +- + if (padapter->bDriverStopped) + goto exit; + +- res = rtw_read8(padapter, REG_LEDCFG2, &LedCfg);/* 0x4E */ +- if (res) +- goto exit; +- +- LedCfg &= 0x90; /* Set to software control. */ +- rtw_write8(padapter, REG_LEDCFG2, (LedCfg | BIT(3))); +- res = rtw_read8(padapter, REG_MAC_PINMUX_CFG, &LedCfg); +- if (res) +- goto exit; +- +- LedCfg &= 0xFE; +- rtw_write8(padapter, REG_MAC_PINMUX_CFG, LedCfg); ++ rtw_write8(padapter, REG_LEDCFG2, BIT(5) | BIT(3)); + exit: + pLed->bLedOn = false; + } +diff --git a/drivers/staging/r8188eu/core/rtw_pwrctrl.c b/drivers/staging/r8188eu/core/rtw_pwrctrl.c +index 870d81735b8dc..5290ac36f08c1 100644 +--- a/drivers/staging/r8188eu/core/rtw_pwrctrl.c ++++ b/drivers/staging/r8188eu/core/rtw_pwrctrl.c +@@ -273,7 +273,7 @@ static s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms) + err = -1; + break; + } +- msleep(1); ++ mdelay(1); + } + + return err; +diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c +index 46d75e925ee9b..f710eb2a95f3a 100644 +--- a/drivers/staging/rtl8192e/rtllib_rx.c ++++ b/drivers/staging/rtl8192e/rtllib_rx.c +@@ -1489,9 +1489,9 @@ static int rtllib_rx_Monitor(struct rtllib_device *ieee, struct sk_buff *skb, + hdrlen += 4; + } + +- rtllib_monitor_rx(ieee, skb, rx_stats, hdrlen); + ieee->stats.rx_packets++; + ieee->stats.rx_bytes += skb->len; ++ rtllib_monitor_rx(ieee, skb, rx_stats, hdrlen); + + return 1; + } +diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +index b58e75932ecd5..3686b3c599ce7 100644 +--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c ++++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +@@ -951,9 +951,11 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, + #endif + + if (ieee->iw_mode == IW_MODE_MONITOR) { ++ unsigned int len = skb->len; ++ + ieee80211_monitor_rx(ieee, skb, rx_stats); + stats->rx_packets++; +- stats->rx_bytes += skb->len; ++ stats->rx_bytes += len; + return 1; + } + +diff --git a/drivers/staging/vme_user/vme_fake.c b/drivers/staging/vme_user/vme_fake.c +index dd646b0c531d4..1ee432c223e2b 100644 +--- a/drivers/staging/vme_user/vme_fake.c ++++ b/drivers/staging/vme_user/vme_fake.c +@@ -1073,6 +1073,8 @@ static int __init fake_init(void) + + /* We need a fake parent device */ + vme_root = __root_device_register("vme", THIS_MODULE); ++ if (IS_ERR(vme_root)) ++ return PTR_ERR(vme_root); + + /* If we want to support more than one bridge at some point, we need to + * dynamically allocate this so we get one per device. +diff --git a/drivers/staging/vme_user/vme_tsi148.c b/drivers/staging/vme_user/vme_tsi148.c +index 020e0b3bce64b..0171f46d1848f 100644 +--- a/drivers/staging/vme_user/vme_tsi148.c ++++ b/drivers/staging/vme_user/vme_tsi148.c +@@ -1751,6 +1751,7 @@ static int tsi148_dma_list_add(struct vme_dma_list *list, + return 0; + + err_dma: ++ list_del(&entry->list); + err_dest: + err_source: + err_align: +diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c +index f2919319ad383..ff49c8f3fe241 100644 +--- a/drivers/target/iscsi/iscsi_target_nego.c ++++ b/drivers/target/iscsi/iscsi_target_nego.c +@@ -1018,6 +1018,13 @@ static int iscsi_target_handle_csg_one(struct iscsit_conn *conn, struct iscsi_lo + return 0; + } + ++/* ++ * RETURN VALUE: ++ * ++ * 1 = Login successful ++ * -1 = Login failed ++ * 0 = More PDU exchanges required ++ */ + static int iscsi_target_do_login(struct iscsit_conn *conn, struct iscsi_login *login) + { + int pdu_count = 0; +@@ -1363,12 +1370,13 @@ int iscsi_target_start_negotiation( + ret = -1; + + if (ret < 0) { +- cancel_delayed_work_sync(&conn->login_work); + iscsi_target_restore_sock_callbacks(conn); + iscsi_remove_failed_auth_entry(conn); + } +- if (ret != 0) ++ if (ret != 0) { ++ cancel_delayed_work_sync(&conn->login_work); + iscsi_target_nego_release(conn); ++ } + + return ret; + } +diff --git a/drivers/thermal/imx8mm_thermal.c b/drivers/thermal/imx8mm_thermal.c +index e2c2673025a7a..258d988b266d7 100644 +--- a/drivers/thermal/imx8mm_thermal.c ++++ b/drivers/thermal/imx8mm_thermal.c +@@ -65,8 +65,14 @@ static int imx8mm_tmu_get_temp(void *data, int *temp) + u32 val; + + val = readl_relaxed(tmu->base + TRITSR) & TRITSR_TEMP0_VAL_MASK; ++ ++ /* ++ * Do not validate against the V bit (bit 31) due to errata ++ * ERR051272: TMU: Bit 31 of registers TMU_TSCR/TMU_TRITSR/TMU_TRATSR invalid ++ */ ++ + *temp = val * 1000; +- if (*temp < VER1_TEMP_LOW_LIMIT) ++ if (*temp < VER1_TEMP_LOW_LIMIT || *temp > VER2_TEMP_HIGH_LIMIT) + return -EAGAIN; + + return 0; +diff --git a/drivers/thermal/k3_j72xx_bandgap.c b/drivers/thermal/k3_j72xx_bandgap.c +index 16b6bcf1bf4fa..c073b1023bbe7 100644 +--- a/drivers/thermal/k3_j72xx_bandgap.c ++++ b/drivers/thermal/k3_j72xx_bandgap.c +@@ -439,7 +439,7 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev) + workaround_needed = false; + + dev_dbg(bgp->dev, "Work around %sneeded\n", +- workaround_needed ? "not " : ""); ++ workaround_needed ? "" : "not "); + + if (!workaround_needed) + init_table(5, ref_table, golden_factors); +diff --git a/drivers/thermal/qcom/lmh.c b/drivers/thermal/qcom/lmh.c +index d3d9b9fa49e81..4122a51e98741 100644 +--- a/drivers/thermal/qcom/lmh.c ++++ b/drivers/thermal/qcom/lmh.c +@@ -45,7 +45,7 @@ static irqreturn_t lmh_handle_irq(int hw_irq, void *data) + if (irq) + generic_handle_irq(irq); + +- return 0; ++ return IRQ_HANDLED; + } + + static void lmh_enable_interrupt(struct irq_data *d) +diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c +index be785ab37e53d..ad84978109e6f 100644 +--- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c ++++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c +@@ -252,7 +252,8 @@ static int qpnp_tm_update_critical_trip_temp(struct qpnp_tm_chip *chip, + disable_s2_shutdown = true; + else + dev_warn(chip->dev, +- "No ADC is configured and critical temperature is above the maximum stage 2 threshold of 140 C! Configuring stage 2 shutdown at 140 C.\n"); ++ "No ADC is configured and critical temperature %d mC is above the maximum stage 2 threshold of %ld mC! Configuring stage 2 shutdown at %ld mC.\n", ++ temp, stage2_threshold_max, stage2_threshold_max); + } + + skip: +diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c +index 117eeaf7dd241..615fdda3a5de7 100644 +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -883,10 +883,6 @@ __thermal_cooling_device_register(struct device_node *np, + 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) { + ret = -ENOMEM; +@@ -901,6 +897,11 @@ __thermal_cooling_device_register(struct device_node *np, + cdev->device.class = &thermal_class; + cdev->devdata = devdata; + thermal_cooling_device_setup_sysfs(cdev); ++ ret = dev_set_name(&cdev->device, "cooling_device%d", cdev->id); ++ if (ret) { ++ thermal_cooling_device_destroy_sysfs(cdev); ++ goto out_kfree_type; ++ } + ret = device_register(&cdev->device); + if (ret) + goto out_kfree_type; +@@ -1234,10 +1235,6 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t + tz->id = id; + strscpy(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; + +@@ -1260,6 +1257,11 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t + /* A new thermal zone needs to be updated anyway. */ + atomic_set(&tz->need_update, 1); + ++ result = dev_set_name(&tz->device, "thermal_zone%d", tz->id); ++ if (result) { ++ thermal_zone_destroy_device_groups(tz); ++ goto remove_id; ++ } + result = device_register(&tz->device); + if (result) + goto release_device; +diff --git a/drivers/thermal/thermal_helpers.c b/drivers/thermal/thermal_helpers.c +index c65cdce8f856e..fca0b23570f96 100644 +--- a/drivers/thermal/thermal_helpers.c ++++ b/drivers/thermal/thermal_helpers.c +@@ -115,7 +115,12 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp) + int ret; + + mutex_lock(&tz->lock); +- ret = __thermal_zone_get_temp(tz, temp); ++ ++ if (device_is_registered(&tz->device)) ++ ret = __thermal_zone_get_temp(tz, temp); ++ else ++ ret = -ENODEV; ++ + mutex_unlock(&tz->lock); + + return ret; +diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c +index d4b6335ace15f..aacba30bc10c1 100644 +--- a/drivers/thermal/thermal_of.c ++++ b/drivers/thermal/thermal_of.c +@@ -604,13 +604,15 @@ struct thermal_zone_device *thermal_of_zone_register(struct device_node *sensor, + if (IS_ERR(np)) { + if (PTR_ERR(np) != -ENODEV) + pr_err("Failed to find thermal zone for %pOFn id=%d\n", sensor, id); +- return ERR_CAST(np); ++ ret = PTR_ERR(np); ++ goto out_kfree_of_ops; + } + + trips = thermal_of_trips_init(np, &ntrips); + if (IS_ERR(trips)) { + pr_err("Failed to find trip points for %pOFn id=%d\n", sensor, id); +- return ERR_CAST(trips); ++ ret = PTR_ERR(trips); ++ goto out_kfree_of_ops; + } + + ret = thermal_of_monitor_init(np, &delay, &pdelay); +@@ -659,6 +661,8 @@ out_kfree_tzp: + kfree(tzp); + out_kfree_trips: + kfree(trips); ++out_kfree_of_ops: ++ kfree(of_ops); + + return ERR_PTR(ret); + } +diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c +index fa8ccf204d860..89bfcefbea848 100644 +--- a/drivers/tty/serial/8250/8250_bcm7271.c ++++ b/drivers/tty/serial/8250/8250_bcm7271.c +@@ -1212,9 +1212,17 @@ static struct platform_driver brcmuart_platform_driver = { + + static int __init brcmuart_init(void) + { ++ int ret; ++ + brcmuart_debugfs_root = debugfs_create_dir( + brcmuart_platform_driver.driver.name, NULL); +- return platform_driver_register(&brcmuart_platform_driver); ++ ret = platform_driver_register(&brcmuart_platform_driver); ++ if (ret) { ++ debugfs_remove_recursive(brcmuart_debugfs_root); ++ return ret; ++ } ++ ++ return 0; + } + module_init(brcmuart_init); + +diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c +index 82f2790de28d1..1203d1e08cd6c 100644 +--- a/drivers/tty/serial/altera_uart.c ++++ b/drivers/tty/serial/altera_uart.c +@@ -278,16 +278,17 @@ static irqreturn_t altera_uart_interrupt(int irq, void *data) + { + struct uart_port *port = data; + struct altera_uart *pp = container_of(port, struct altera_uart, port); ++ unsigned long flags; + unsigned int isr; + + isr = altera_uart_readl(port, ALTERA_UART_STATUS_REG) & pp->imr; + +- spin_lock(&port->lock); ++ spin_lock_irqsave(&port->lock, flags); + if (isr & ALTERA_UART_STATUS_RRDY_MSK) + altera_uart_rx_chars(port); + if (isr & ALTERA_UART_STATUS_TRDY_MSK) + altera_uart_tx_chars(port); +- spin_unlock(&port->lock); ++ spin_unlock_irqrestore(&port->lock, flags); + + return IRQ_RETVAL(isr); + } +diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c +index 5cdced39eafdb..aa0bbb7abeacf 100644 +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -1045,6 +1045,9 @@ static void pl011_dma_rx_callback(void *data) + */ + static inline void pl011_dma_rx_stop(struct uart_amba_port *uap) + { ++ if (!uap->using_rx_dma) ++ return; ++ + /* FIXME. Just disable the DMA enable */ + uap->dmacr &= ~UART011_RXDMAE; + pl011_write(uap->dmacr, uap, REG_DMACR); +@@ -1828,8 +1831,17 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap) + static void pl011_unthrottle_rx(struct uart_port *port) + { + struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); ++ unsigned long flags; + +- pl011_enable_interrupts(uap); ++ spin_lock_irqsave(&uap->port.lock, flags); ++ ++ uap->im = UART011_RTIM; ++ if (!pl011_dma_rx_running(uap)) ++ uap->im |= UART011_RXIM; ++ ++ pl011_write(uap->im, uap, REG_IMSC); ++ ++ spin_unlock_irqrestore(&uap->port.lock, flags); + } + + static int pl011_startup(struct uart_port *port) +diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c +index c59ce78865799..b17788cf309b1 100644 +--- a/drivers/tty/serial/pch_uart.c ++++ b/drivers/tty/serial/pch_uart.c +@@ -694,6 +694,7 @@ static void pch_request_dma(struct uart_port *port) + if (!chan) { + dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Tx)\n", + __func__); ++ pci_dev_put(dma_dev); + return; + } + priv->chan_tx = chan; +@@ -710,6 +711,7 @@ static void pch_request_dma(struct uart_port *port) + __func__); + dma_release_channel(priv->chan_tx); + priv->chan_tx = NULL; ++ pci_dev_put(dma_dev); + return; + } + +@@ -717,6 +719,8 @@ static void pch_request_dma(struct uart_port *port) + priv->rx_buf_virt = dma_alloc_coherent(port->dev, port->fifosize, + &priv->rx_buf_dma, GFP_KERNEL); + priv->chan_rx = chan; ++ ++ pci_dev_put(dma_dev); + } + + static void pch_dma_rx_complete(void *arg) +diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c +index b7170cb9a544f..cda9cd4fa92c8 100644 +--- a/drivers/tty/serial/serial-tegra.c ++++ b/drivers/tty/serial/serial-tegra.c +@@ -619,8 +619,9 @@ static void tegra_uart_stop_tx(struct uart_port *u) + if (tup->tx_in_progress != TEGRA_UART_TX_DMA) + return; + +- dmaengine_terminate_all(tup->tx_dma_chan); ++ dmaengine_pause(tup->tx_dma_chan); + dmaengine_tx_status(tup->tx_dma_chan, tup->tx_cookie, &state); ++ dmaengine_terminate_all(tup->tx_dma_chan); + count = tup->tx_bytes_requested - state.residue; + async_tx_ack(tup->tx_dma_desc); + uart_xmit_advance(&tup->uport, count); +@@ -763,8 +764,9 @@ static void tegra_uart_terminate_rx_dma(struct tegra_uart_port *tup) + return; + } + +- dmaengine_terminate_all(tup->rx_dma_chan); ++ dmaengine_pause(tup->rx_dma_chan); + dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state); ++ dmaengine_terminate_all(tup->rx_dma_chan); + + tegra_uart_rx_buffer_push(tup, state.residue); + tup->rx_dma_active = false; +diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c +index dfdbcf092facc..b8aed28b8f17b 100644 +--- a/drivers/tty/serial/stm32-usart.c ++++ b/drivers/tty/serial/stm32-usart.c +@@ -1681,22 +1681,10 @@ static int stm32_usart_serial_probe(struct platform_device *pdev) + if (!stm32port->info) + return -EINVAL; + +- ret = stm32_usart_init_port(stm32port, pdev); +- if (ret) +- return ret; +- +- if (stm32port->wakeup_src) { +- device_set_wakeup_capable(&pdev->dev, true); +- ret = dev_pm_set_wake_irq(&pdev->dev, stm32port->port.irq); +- if (ret) +- goto err_deinit_port; +- } +- + stm32port->rx_ch = dma_request_chan(&pdev->dev, "rx"); +- if (PTR_ERR(stm32port->rx_ch) == -EPROBE_DEFER) { +- ret = -EPROBE_DEFER; +- goto err_wakeirq; +- } ++ if (PTR_ERR(stm32port->rx_ch) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ + /* Fall back in interrupt mode for any non-deferral error */ + if (IS_ERR(stm32port->rx_ch)) + stm32port->rx_ch = NULL; +@@ -1710,6 +1698,17 @@ static int stm32_usart_serial_probe(struct platform_device *pdev) + if (IS_ERR(stm32port->tx_ch)) + stm32port->tx_ch = NULL; + ++ ret = stm32_usart_init_port(stm32port, pdev); ++ if (ret) ++ goto err_dma_tx; ++ ++ if (stm32port->wakeup_src) { ++ device_set_wakeup_capable(&pdev->dev, true); ++ ret = dev_pm_set_wake_irq(&pdev->dev, stm32port->port.irq); ++ if (ret) ++ goto err_deinit_port; ++ } ++ + if (stm32port->rx_ch && stm32_usart_of_dma_rx_probe(stm32port, pdev)) { + /* Fall back in interrupt mode */ + dma_release_channel(stm32port->rx_ch); +@@ -1746,19 +1745,11 @@ err_port: + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); + +- if (stm32port->tx_ch) { ++ if (stm32port->tx_ch) + stm32_usart_of_dma_tx_remove(stm32port, pdev); +- dma_release_channel(stm32port->tx_ch); +- } +- + if (stm32port->rx_ch) + stm32_usart_of_dma_rx_remove(stm32port, pdev); + +-err_dma_rx: +- if (stm32port->rx_ch) +- dma_release_channel(stm32port->rx_ch); +- +-err_wakeirq: + if (stm32port->wakeup_src) + dev_pm_clear_wake_irq(&pdev->dev); + +@@ -1768,6 +1759,14 @@ err_deinit_port: + + stm32_usart_deinit_port(stm32port); + ++err_dma_tx: ++ if (stm32port->tx_ch) ++ dma_release_channel(stm32port->tx_ch); ++ ++err_dma_rx: ++ if (stm32port->rx_ch) ++ dma_release_channel(stm32port->rx_ch); ++ + return ret; + } + +diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c +index 99608b2a2b74f..7ace3aa498402 100644 +--- a/drivers/tty/serial/sunsab.c ++++ b/drivers/tty/serial/sunsab.c +@@ -1133,7 +1133,13 @@ static int __init sunsab_init(void) + } + } + +- return platform_driver_register(&sab_driver); ++ err = platform_driver_register(&sab_driver); ++ if (err) { ++ kfree(sunsab_ports); ++ sunsab_ports = NULL; ++ } ++ ++ return err; + } + + static void __exit sunsab_exit(void) +diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c +index b1f59a5fe6327..d1db6be801560 100644 +--- a/drivers/ufs/core/ufshcd.c ++++ b/drivers/ufs/core/ufshcd.c +@@ -5382,6 +5382,26 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba, + } + } + ++/* Any value that is not an existing queue number is fine for this constant. */ ++enum { ++ UFSHCD_POLL_FROM_INTERRUPT_CONTEXT = -1 ++}; ++ ++static void ufshcd_clear_polled(struct ufs_hba *hba, ++ unsigned long *completed_reqs) ++{ ++ int tag; ++ ++ for_each_set_bit(tag, completed_reqs, hba->nutrs) { ++ struct scsi_cmnd *cmd = hba->lrb[tag].cmd; ++ ++ if (!cmd) ++ continue; ++ if (scsi_cmd_to_rq(cmd)->cmd_flags & REQ_POLLED) ++ __clear_bit(tag, completed_reqs); ++ } ++} ++ + /* + * Returns > 0 if one or more commands have been completed or 0 if no + * requests have been completed. +@@ -5398,13 +5418,17 @@ static int ufshcd_poll(struct Scsi_Host *shost, unsigned int queue_num) + WARN_ONCE(completed_reqs & ~hba->outstanding_reqs, + "completed: %#lx; outstanding: %#lx\n", completed_reqs, + hba->outstanding_reqs); ++ if (queue_num == UFSHCD_POLL_FROM_INTERRUPT_CONTEXT) { ++ /* Do not complete polled requests from interrupt context. */ ++ ufshcd_clear_polled(hba, &completed_reqs); ++ } + hba->outstanding_reqs &= ~completed_reqs; + spin_unlock_irqrestore(&hba->outstanding_lock, flags); + + if (completed_reqs) + __ufshcd_transfer_req_compl(hba, completed_reqs); + +- return completed_reqs; ++ return completed_reqs != 0; + } + + /** +@@ -5435,7 +5459,7 @@ static irqreturn_t ufshcd_transfer_req_compl(struct ufs_hba *hba) + * Ignore the ufshcd_poll() return value and return IRQ_HANDLED since we + * do not want polling to trigger spurious interrupt complaints. + */ +- ufshcd_poll(hba->host, 0); ++ ufshcd_poll(hba->host, UFSHCD_POLL_FROM_INTERRUPT_CONTEXT); + + return IRQ_HANDLED; + } +@@ -8747,8 +8771,6 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, + struct scsi_device *sdp; + unsigned long flags; + int ret, retries; +- unsigned long deadline; +- int32_t remaining; + + spin_lock_irqsave(hba->host->host_lock, flags); + sdp = hba->ufs_device_wlun; +@@ -8781,14 +8803,9 @@ 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. + */ +- deadline = jiffies + 10 * HZ; + for (retries = 3; retries > 0; --retries) { +- ret = -ETIMEDOUT; +- remaining = deadline - jiffies; +- if (remaining <= 0) +- break; + ret = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr, +- remaining / HZ, 0, 0, RQF_PM, NULL); ++ HZ, 0, 0, RQF_PM, NULL); + if (!scsi_status_is_check_condition(ret) || + !scsi_sense_valid(&sshdr) || + sshdr.sense_key != UNIT_ATTENTION) +diff --git a/drivers/uio/uio_dmem_genirq.c b/drivers/uio/uio_dmem_genirq.c +index 1106f33764047..792c3e9c9ce53 100644 +--- a/drivers/uio/uio_dmem_genirq.c ++++ b/drivers/uio/uio_dmem_genirq.c +@@ -110,8 +110,10 @@ static irqreturn_t uio_dmem_genirq_handler(int irq, struct uio_info *dev_info) + * remember the state so we can allow user space to enable it later. + */ + ++ spin_lock(&priv->lock); + if (!test_and_set_bit(0, &priv->flags)) + disable_irq_nosync(irq); ++ spin_unlock(&priv->lock); + + return IRQ_HANDLED; + } +@@ -125,20 +127,19 @@ static int uio_dmem_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on) + * in the interrupt controller, but keep track of the + * state to prevent per-irq depth damage. + * +- * Serialize this operation to support multiple tasks. ++ * Serialize this operation to support multiple tasks and concurrency ++ * with irq handler on SMP systems. + */ + + spin_lock_irqsave(&priv->lock, flags); + if (irq_on) { + if (test_and_clear_bit(0, &priv->flags)) + enable_irq(dev_info->irq); +- spin_unlock_irqrestore(&priv->lock, flags); + } else { +- if (!test_and_set_bit(0, &priv->flags)) { +- spin_unlock_irqrestore(&priv->lock, flags); +- disable_irq(dev_info->irq); +- } ++ if (!test_and_set_bit(0, &priv->flags)) ++ disable_irq_nosync(dev_info->irq); + } ++ spin_unlock_irqrestore(&priv->lock, flags); + + return 0; + } +diff --git a/drivers/usb/cdns3/cdnsp-ring.c b/drivers/usb/cdns3/cdnsp-ring.c +index 2f29431f612e0..b23e543b3a3d5 100644 +--- a/drivers/usb/cdns3/cdnsp-ring.c ++++ b/drivers/usb/cdns3/cdnsp-ring.c +@@ -2006,10 +2006,11 @@ int cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq) + + int cdnsp_queue_ctrl_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq) + { +- u32 field, length_field, remainder; ++ u32 field, length_field, zlp = 0; + struct cdnsp_ep *pep = preq->pep; + struct cdnsp_ring *ep_ring; + int num_trbs; ++ u32 maxp; + int ret; + + ep_ring = cdnsp_request_to_transfer_ring(pdev, preq); +@@ -2019,26 +2020,33 @@ int cdnsp_queue_ctrl_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq) + /* 1 TRB for data, 1 for status */ + num_trbs = (pdev->three_stage_setup) ? 2 : 1; + ++ maxp = usb_endpoint_maxp(pep->endpoint.desc); ++ ++ if (preq->request.zero && preq->request.length && ++ (preq->request.length % maxp == 0)) { ++ num_trbs++; ++ zlp = 1; ++ } ++ + ret = cdnsp_prepare_transfer(pdev, preq, num_trbs); + if (ret) + return ret; + + /* If there's data, queue data TRBs */ +- if (pdev->ep0_expect_in) +- field = TRB_TYPE(TRB_DATA) | TRB_IOC; +- else +- field = TRB_ISP | TRB_TYPE(TRB_DATA) | TRB_IOC; +- + if (preq->request.length > 0) { +- remainder = cdnsp_td_remainder(pdev, 0, preq->request.length, +- preq->request.length, preq, 1, 0); ++ field = TRB_TYPE(TRB_DATA); + +- length_field = TRB_LEN(preq->request.length) | +- TRB_TD_SIZE(remainder) | TRB_INTR_TARGET(0); ++ if (zlp) ++ field |= TRB_CHAIN; ++ else ++ field |= TRB_IOC | (pdev->ep0_expect_in ? 0 : TRB_ISP); + + if (pdev->ep0_expect_in) + field |= TRB_DIR_IN; + ++ length_field = TRB_LEN(preq->request.length) | ++ TRB_TD_SIZE(zlp) | TRB_INTR_TARGET(0); ++ + cdnsp_queue_trb(pdev, ep_ring, true, + lower_32_bits(preq->request.dma), + upper_32_bits(preq->request.dma), length_field, +@@ -2046,6 +2054,20 @@ int cdnsp_queue_ctrl_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq) + TRB_SETUPID(pdev->setup_id) | + pdev->setup_speed); + ++ if (zlp) { ++ field = TRB_TYPE(TRB_NORMAL) | TRB_IOC; ++ ++ if (!pdev->ep0_expect_in) ++ field = TRB_ISP; ++ ++ cdnsp_queue_trb(pdev, ep_ring, true, ++ lower_32_bits(preq->request.dma), ++ upper_32_bits(preq->request.dma), 0, ++ field | ep_ring->cycle_state | ++ TRB_SETUPID(pdev->setup_id) | ++ pdev->setup_speed); ++ } ++ + pdev->ep0_stage = CDNSP_DATA_STAGE; + } + +diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c +index faeaace0d197d..8300baedafd20 100644 +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -3133,8 +3133,12 @@ int usb_hcd_setup_local_mem(struct usb_hcd *hcd, phys_addr_t phys_addr, + GFP_KERNEL, + DMA_ATTR_WRITE_COMBINE); + +- if (IS_ERR(local_mem)) ++ if (IS_ERR_OR_NULL(local_mem)) { ++ if (!local_mem) ++ return -ENOMEM; ++ + return PTR_ERR(local_mem); ++ } + + /* + * Here we pass a dma_addr_t but the arg type is a phys_addr_t. +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index 1f348bc867c22..476b636185116 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -122,21 +122,25 @@ static void __dwc3_set_mode(struct work_struct *work) + unsigned long flags; + int ret; + u32 reg; ++ u32 desired_dr_role; + + mutex_lock(&dwc->mutex); ++ spin_lock_irqsave(&dwc->lock, flags); ++ desired_dr_role = dwc->desired_dr_role; ++ spin_unlock_irqrestore(&dwc->lock, flags); + + pm_runtime_get_sync(dwc->dev); + + if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_OTG) + dwc3_otg_update(dwc, 0); + +- if (!dwc->desired_dr_role) ++ if (!desired_dr_role) + goto out; + +- if (dwc->desired_dr_role == dwc->current_dr_role) ++ if (desired_dr_role == dwc->current_dr_role) + goto out; + +- if (dwc->desired_dr_role == DWC3_GCTL_PRTCAP_OTG && dwc->edev) ++ if (desired_dr_role == DWC3_GCTL_PRTCAP_OTG && dwc->edev) + goto out; + + switch (dwc->current_dr_role) { +@@ -164,7 +168,7 @@ static void __dwc3_set_mode(struct work_struct *work) + */ + if (dwc->current_dr_role && ((DWC3_IP_IS(DWC3) || + DWC3_VER_IS_PRIOR(DWC31, 190A)) && +- dwc->desired_dr_role != DWC3_GCTL_PRTCAP_OTG)) { ++ desired_dr_role != DWC3_GCTL_PRTCAP_OTG)) { + reg = dwc3_readl(dwc->regs, DWC3_GCTL); + reg |= DWC3_GCTL_CORESOFTRESET; + dwc3_writel(dwc->regs, DWC3_GCTL, reg); +@@ -184,11 +188,11 @@ static void __dwc3_set_mode(struct work_struct *work) + + spin_lock_irqsave(&dwc->lock, flags); + +- dwc3_set_prtcap(dwc, dwc->desired_dr_role); ++ dwc3_set_prtcap(dwc, desired_dr_role); + + spin_unlock_irqrestore(&dwc->lock, flags); + +- switch (dwc->desired_dr_role) { ++ switch (desired_dr_role) { + case DWC3_GCTL_PRTCAP_HOST: + ret = dwc3_host_init(dwc); + if (ret) { +@@ -1096,8 +1100,13 @@ static int dwc3_core_init(struct dwc3 *dwc) + + if (!dwc->ulpi_ready) { + ret = dwc3_core_ulpi_init(dwc); +- if (ret) ++ if (ret) { ++ if (ret == -ETIMEDOUT) { ++ dwc3_core_soft_reset(dwc); ++ ret = -EPROBE_DEFER; ++ } + goto err0; ++ } + dwc->ulpi_ready = true; + } + +diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c +index fb14511b1e10f..89c9ab2b19f85 100644 +--- a/drivers/usb/dwc3/dwc3-pci.c ++++ b/drivers/usb/dwc3/dwc3-pci.c +@@ -45,7 +45,7 @@ + #define PCI_DEVICE_ID_INTEL_ADLN 0x465e + #define PCI_DEVICE_ID_INTEL_ADLN_PCH 0x54ee + #define PCI_DEVICE_ID_INTEL_ADLS 0x7ae1 +-#define PCI_DEVICE_ID_INTEL_RPL 0x460e ++#define PCI_DEVICE_ID_INTEL_RPL 0xa70e + #define PCI_DEVICE_ID_INTEL_RPLS 0x7a61 + #define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1 + #define PCI_DEVICE_ID_INTEL_MTL 0x7e7e +diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c +index 7c40f3ffc0544..b0a0351d2d8b5 100644 +--- a/drivers/usb/dwc3/dwc3-qcom.c ++++ b/drivers/usb/dwc3/dwc3-qcom.c +@@ -261,7 +261,8 @@ static int dwc3_qcom_interconnect_init(struct dwc3_qcom *qcom) + if (IS_ERR(qcom->icc_path_apps)) { + dev_err(dev, "failed to get apps-usb path: %ld\n", + PTR_ERR(qcom->icc_path_apps)); +- return PTR_ERR(qcom->icc_path_apps); ++ ret = PTR_ERR(qcom->icc_path_apps); ++ goto put_path_ddr; + } + + max_speed = usb_get_maximum_speed(&qcom->dwc3->dev); +@@ -274,16 +275,22 @@ static int dwc3_qcom_interconnect_init(struct dwc3_qcom *qcom) + } + if (ret) { + dev_err(dev, "failed to set bandwidth for usb-ddr path: %d\n", ret); +- return ret; ++ goto put_path_apps; + } + + ret = icc_set_bw(qcom->icc_path_apps, APPS_USB_AVG_BW, APPS_USB_PEAK_BW); + if (ret) { + dev_err(dev, "failed to set bandwidth for apps-usb path: %d\n", ret); +- return ret; ++ goto put_path_apps; + } + + return 0; ++ ++put_path_apps: ++ icc_put(qcom->icc_path_apps); ++put_path_ddr: ++ icc_put(qcom->icc_path_ddr); ++ return ret; + } + + /** +diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c +index ca0a7d9eaa34e..6be6009f911e1 100644 +--- a/drivers/usb/gadget/function/f_hid.c ++++ b/drivers/usb/gadget/function/f_hid.c +@@ -71,7 +71,7 @@ struct f_hidg { + wait_queue_head_t write_queue; + struct usb_request *req; + +- int minor; ++ struct device dev; + struct cdev cdev; + struct usb_function func; + +@@ -84,6 +84,14 @@ static inline struct f_hidg *func_to_hidg(struct usb_function *f) + return container_of(f, struct f_hidg, func); + } + ++static void hidg_release(struct device *dev) ++{ ++ struct f_hidg *hidg = container_of(dev, struct f_hidg, dev); ++ ++ kfree(hidg->set_report_buf); ++ kfree(hidg); ++} ++ + /*-------------------------------------------------------------------------*/ + /* Static descriptors */ + +@@ -904,9 +912,7 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) + struct usb_ep *ep; + struct f_hidg *hidg = func_to_hidg(f); + struct usb_string *us; +- struct device *device; + int status; +- dev_t dev; + + /* maybe allocate device-global string IDs, and patch descriptors */ + us = usb_gstrings_attach(c->cdev, ct_func_strings, +@@ -999,21 +1005,11 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) + + /* create char device */ + cdev_init(&hidg->cdev, &f_hidg_fops); +- dev = MKDEV(major, hidg->minor); +- status = cdev_add(&hidg->cdev, dev, 1); ++ status = cdev_device_add(&hidg->cdev, &hidg->dev); + if (status) + goto fail_free_descs; + +- device = device_create(hidg_class, NULL, dev, NULL, +- "%s%d", "hidg", hidg->minor); +- if (IS_ERR(device)) { +- status = PTR_ERR(device); +- goto del; +- } +- + return 0; +-del: +- cdev_del(&hidg->cdev); + fail_free_descs: + usb_free_all_descriptors(f); + fail: +@@ -1244,9 +1240,7 @@ static void hidg_free(struct usb_function *f) + + hidg = func_to_hidg(f); + opts = container_of(f->fi, struct f_hid_opts, func_inst); +- kfree(hidg->report_desc); +- kfree(hidg->set_report_buf); +- kfree(hidg); ++ put_device(&hidg->dev); + mutex_lock(&opts->lock); + --opts->refcnt; + mutex_unlock(&opts->lock); +@@ -1256,8 +1250,7 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f) + { + struct f_hidg *hidg = func_to_hidg(f); + +- device_destroy(hidg_class, MKDEV(major, hidg->minor)); +- cdev_del(&hidg->cdev); ++ cdev_device_del(&hidg->cdev, &hidg->dev); + + usb_free_all_descriptors(f); + } +@@ -1266,6 +1259,7 @@ static struct usb_function *hidg_alloc(struct usb_function_instance *fi) + { + struct f_hidg *hidg; + struct f_hid_opts *opts; ++ int ret; + + /* allocate and initialize one new instance */ + hidg = kzalloc(sizeof(*hidg), GFP_KERNEL); +@@ -1277,17 +1271,28 @@ static struct usb_function *hidg_alloc(struct usb_function_instance *fi) + mutex_lock(&opts->lock); + ++opts->refcnt; + +- hidg->minor = opts->minor; ++ device_initialize(&hidg->dev); ++ hidg->dev.release = hidg_release; ++ hidg->dev.class = hidg_class; ++ hidg->dev.devt = MKDEV(major, opts->minor); ++ ret = dev_set_name(&hidg->dev, "hidg%d", opts->minor); ++ if (ret) { ++ --opts->refcnt; ++ mutex_unlock(&opts->lock); ++ return ERR_PTR(ret); ++ } ++ + hidg->bInterfaceSubClass = opts->subclass; + hidg->bInterfaceProtocol = opts->protocol; + hidg->report_length = opts->report_length; + hidg->report_desc_length = opts->report_desc_length; + if (opts->report_desc) { +- hidg->report_desc = kmemdup(opts->report_desc, +- opts->report_desc_length, +- GFP_KERNEL); ++ hidg->report_desc = devm_kmemdup(&hidg->dev, opts->report_desc, ++ opts->report_desc_length, ++ GFP_KERNEL); + if (!hidg->report_desc) { +- kfree(hidg); ++ put_device(&hidg->dev); ++ --opts->refcnt; + mutex_unlock(&opts->lock); + return ERR_PTR(-ENOMEM); + } +diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c +index 6e196e06181ec..4419b7972e78f 100644 +--- a/drivers/usb/gadget/function/f_uvc.c ++++ b/drivers/usb/gadget/function/f_uvc.c +@@ -216,8 +216,9 @@ uvc_function_ep0_complete(struct usb_ep *ep, struct usb_request *req) + + memset(&v4l2_event, 0, sizeof(v4l2_event)); + v4l2_event.type = UVC_EVENT_DATA; +- uvc_event->data.length = req->actual; +- memcpy(&uvc_event->data.data, req->buf, req->actual); ++ uvc_event->data.length = min_t(unsigned int, req->actual, ++ sizeof(uvc_event->data.data)); ++ memcpy(&uvc_event->data.data, req->buf, uvc_event->data.length); + v4l2_event_queue(&uvc->vdev, &v4l2_event); + } + } +diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c +index c63c0c2cf649d..bf9878e1a72a8 100644 +--- a/drivers/usb/gadget/udc/core.c ++++ b/drivers/usb/gadget/udc/core.c +@@ -734,13 +734,13 @@ int usb_gadget_disconnect(struct usb_gadget *gadget) + } + + ret = gadget->ops->pullup(gadget, 0); +- if (!ret) { ++ if (!ret) + gadget->connected = 0; +- mutex_lock(&udc_lock); +- if (gadget->udc->driver) +- gadget->udc->driver->disconnect(gadget); +- mutex_unlock(&udc_lock); +- } ++ ++ mutex_lock(&udc_lock); ++ if (gadget->udc->driver) ++ gadget->udc->driver->disconnect(gadget); ++ mutex_unlock(&udc_lock); + + out: + trace_usb_gadget_disconnect(gadget, ret); +diff --git a/drivers/usb/gadget/udc/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c +index fdca28e72a3b4..d0e051beb3af9 100644 +--- a/drivers/usb/gadget/udc/fotg210-udc.c ++++ b/drivers/usb/gadget/udc/fotg210-udc.c +@@ -629,10 +629,10 @@ static void fotg210_request_error(struct fotg210_udc *fotg210) + static void fotg210_set_address(struct fotg210_udc *fotg210, + struct usb_ctrlrequest *ctrl) + { +- if (ctrl->wValue >= 0x0100) { ++ if (le16_to_cpu(ctrl->wValue) >= 0x0100) { + fotg210_request_error(fotg210); + } else { +- fotg210_set_dev_addr(fotg210, ctrl->wValue); ++ fotg210_set_dev_addr(fotg210, le16_to_cpu(ctrl->wValue)); + fotg210_set_cxdone(fotg210); + } + } +@@ -713,17 +713,17 @@ static void fotg210_get_status(struct fotg210_udc *fotg210, + + switch (ctrl->bRequestType & USB_RECIP_MASK) { + case USB_RECIP_DEVICE: +- fotg210->ep0_data = 1 << USB_DEVICE_SELF_POWERED; ++ fotg210->ep0_data = cpu_to_le16(1 << USB_DEVICE_SELF_POWERED); + break; + case USB_RECIP_INTERFACE: +- fotg210->ep0_data = 0; ++ fotg210->ep0_data = cpu_to_le16(0); + break; + case USB_RECIP_ENDPOINT: + epnum = ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK; + if (epnum) + fotg210->ep0_data = +- fotg210_is_epnstall(fotg210->ep[epnum]) +- << USB_ENDPOINT_HALT; ++ cpu_to_le16(fotg210_is_epnstall(fotg210->ep[epnum]) ++ << USB_ENDPOINT_HALT); + else + fotg210_request_error(fotg210); + break; +diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c +index 01705e559c422..c61fc19ef1154 100644 +--- a/drivers/usb/host/xhci-mtk.c ++++ b/drivers/usb/host/xhci-mtk.c +@@ -639,7 +639,6 @@ static int xhci_mtk_probe(struct platform_device *pdev) + + dealloc_usb3_hcd: + usb_remove_hcd(xhci->shared_hcd); +- xhci->shared_hcd = NULL; + + dealloc_usb2_hcd: + usb_remove_hcd(hcd); +diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c +index 7bccbe50bab15..f98cf30a3c1a5 100644 +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -59,6 +59,7 @@ + #define PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI 0x9a13 + #define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI 0x1138 + #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed ++#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_PCH_XHCI 0x54ed + + #define PCI_DEVICE_ID_AMD_RENOIR_XHCI 0x1639 + #define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9 +@@ -246,7 +247,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + xhci->quirks |= XHCI_MISSING_CAS; + + if (pdev->vendor == PCI_VENDOR_ID_INTEL && +- pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI) ++ (pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI || ++ pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_PCH_XHCI)) + xhci->quirks |= XHCI_RESET_TO_DEFAULT; + + if (pdev->vendor == PCI_VENDOR_ID_INTEL && +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index ad81e9a508b14..343709af4c16f 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -2458,7 +2458,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, + + switch (trb_comp_code) { + case COMP_SUCCESS: +- ep_ring->err_count = 0; ++ ep->err_count = 0; + /* handle success with untransferred data as short packet */ + if (ep_trb != td->last_trb || remaining) { + xhci_warn(xhci, "WARN Successful completion on short TX\n"); +@@ -2484,7 +2484,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, + break; + case COMP_USB_TRANSACTION_ERROR: + if (xhci->quirks & XHCI_NO_SOFT_RETRY || +- (ep_ring->err_count++ > MAX_SOFT_RETRY) || ++ (ep->err_count++ > MAX_SOFT_RETRY) || + le32_to_cpu(slot_ctx->tt_info) & TT_SLOT) + break; + +@@ -2565,8 +2565,14 @@ static int handle_tx_event(struct xhci_hcd *xhci, + case COMP_USB_TRANSACTION_ERROR: + case COMP_INVALID_STREAM_TYPE_ERROR: + case COMP_INVALID_STREAM_ID_ERROR: +- xhci_handle_halted_endpoint(xhci, ep, 0, NULL, +- EP_SOFT_RESET); ++ xhci_dbg(xhci, "Stream transaction error ep %u no id\n", ++ ep_index); ++ if (ep->err_count++ > MAX_SOFT_RETRY) ++ xhci_handle_halted_endpoint(xhci, ep, 0, NULL, ++ EP_HARD_RESET); ++ else ++ xhci_handle_halted_endpoint(xhci, ep, 0, NULL, ++ EP_SOFT_RESET); + goto cleanup; + case COMP_RING_UNDERRUN: + case COMP_RING_OVERRUN: +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index cc084d9505cdf..c9f06c5e4e9d2 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -933,6 +933,7 @@ struct xhci_virt_ep { + * have to restore the device state to the previous state + */ + struct xhci_ring *new_ring; ++ unsigned int err_count; + unsigned int ep_state; + #define SET_DEQ_PENDING (1 << 0) + #define EP_HALTED (1 << 1) /* For stall handling */ +@@ -1627,7 +1628,6 @@ struct xhci_ring { + * if we own the TRB (if we are the consumer). See section 4.9.1. + */ + u32 cycle_state; +- unsigned int err_count; + unsigned int stream_id; + unsigned int num_segs; + unsigned int num_trbs_free; +diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c +index 6704a62a16659..ba20272d22215 100644 +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -1628,8 +1628,6 @@ static int musb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA) + { + struct musb *musb = gadget_to_musb(gadget); + +- if (!musb->xceiv->set_power) +- return -EOPNOTSUPP; + return usb_phy_set_power(musb->xceiv, mA); + } + +diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c +index f571a65ae6ee2..476f55d1fec30 100644 +--- a/drivers/usb/musb/omap2430.c ++++ b/drivers/usb/musb/omap2430.c +@@ -15,6 +15,7 @@ + #include <linux/list.h> + #include <linux/io.h> + #include <linux/of.h> ++#include <linux/of_irq.h> + #include <linux/platform_device.h> + #include <linux/dma-mapping.h> + #include <linux/pm_runtime.h> +@@ -310,6 +311,7 @@ static int omap2430_probe(struct platform_device *pdev) + struct device_node *control_node; + struct platform_device *control_pdev; + int ret = -ENOMEM, val; ++ bool populate_irqs = false; + + if (!np) + return -ENODEV; +@@ -328,6 +330,18 @@ static int omap2430_probe(struct platform_device *pdev) + musb->dev.dma_mask = &omap2430_dmamask; + musb->dev.coherent_dma_mask = omap2430_dmamask; + ++ /* ++ * Legacy SoCs using omap_device get confused if node is moved ++ * because of interconnect properties mixed into the node. ++ */ ++ if (of_get_property(np, "ti,hwmods", NULL)) { ++ dev_warn(&pdev->dev, "please update to probe with ti-sysc\n"); ++ populate_irqs = true; ++ } else { ++ device_set_of_node_from_dev(&musb->dev, &pdev->dev); ++ } ++ of_node_put(np); ++ + glue->dev = &pdev->dev; + glue->musb = musb; + glue->status = MUSB_UNKNOWN; +@@ -389,6 +403,46 @@ static int omap2430_probe(struct platform_device *pdev) + goto err2; + } + ++ if (populate_irqs) { ++ struct resource musb_res[3]; ++ struct resource *res; ++ int i = 0; ++ ++ memset(musb_res, 0, sizeof(*musb_res) * ARRAY_SIZE(musb_res)); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) ++ goto err2; ++ ++ musb_res[i].start = res->start; ++ musb_res[i].end = res->end; ++ musb_res[i].flags = res->flags; ++ musb_res[i].name = res->name; ++ i++; ++ ++ ret = of_irq_get_byname(np, "mc"); ++ if (ret > 0) { ++ musb_res[i].start = ret; ++ musb_res[i].flags = IORESOURCE_IRQ; ++ musb_res[i].name = "mc"; ++ i++; ++ } ++ ++ ret = of_irq_get_byname(np, "dma"); ++ if (ret > 0) { ++ musb_res[i].start = ret; ++ musb_res[i].flags = IORESOURCE_IRQ; ++ musb_res[i].name = "dma"; ++ i++; ++ } ++ ++ ret = platform_device_add_resources(musb, musb_res, i); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to add IRQ resources\n"); ++ goto err2; ++ } ++ } ++ + ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); + if (ret) { + dev_err(&pdev->dev, "failed to add platform_data\n"); +diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c +index dfaed7eee94fc..32e6d19f7011a 100644 +--- a/drivers/usb/roles/class.c ++++ b/drivers/usb/roles/class.c +@@ -106,10 +106,13 @@ usb_role_switch_is_parent(struct fwnode_handle *fwnode) + struct fwnode_handle *parent = fwnode_get_parent(fwnode); + struct device *dev; + +- if (!parent || !fwnode_property_present(parent, "usb-role-switch")) ++ if (!fwnode_property_present(parent, "usb-role-switch")) { ++ fwnode_handle_put(parent); + return NULL; ++ } + + dev = class_find_device_by_fwnode(role_class, parent); ++ fwnode_handle_put(parent); + return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER); + } + +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index 3bcec419f4632..f6fb23620e87a 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -195,6 +195,8 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */ + { USB_DEVICE(0x17A8, 0x0001) }, /* Kamstrup Optical Eye/3-wire */ + { USB_DEVICE(0x17A8, 0x0005) }, /* Kamstrup M-Bus Master MultiPort 250D */ ++ { USB_DEVICE(0x17A8, 0x0011) }, /* Kamstrup 444 MHz RF sniffer */ ++ { USB_DEVICE(0x17A8, 0x0013) }, /* Kamstrup 870 MHz RF sniffer */ + { USB_DEVICE(0x17A8, 0x0101) }, /* Kamstrup 868 MHz wM-Bus C-Mode Meter Reader (Int Ant) */ + { USB_DEVICE(0x17A8, 0x0102) }, /* Kamstrup 868 MHz wM-Bus C-Mode Meter Reader (Ext Ant) */ + { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ +diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c +index 2dd58cd9f0ccb..891fb1fe69df7 100644 +--- a/drivers/usb/serial/f81232.c ++++ b/drivers/usb/serial/f81232.c +@@ -130,9 +130,6 @@ static u8 const clock_table[] = { F81232_CLK_1_846_MHZ, F81232_CLK_14_77_MHZ, + + static int calc_baud_divisor(speed_t baudrate, speed_t clockrate) + { +- if (!baudrate) +- return 0; +- + return DIV_ROUND_CLOSEST(clockrate, baudrate); + } + +@@ -498,9 +495,14 @@ static void f81232_set_baudrate(struct tty_struct *tty, + speed_t baud_list[] = { baudrate, old_baudrate, F81232_DEF_BAUDRATE }; + + for (i = 0; i < ARRAY_SIZE(baud_list); ++i) { +- idx = f81232_find_clk(baud_list[i]); ++ baudrate = baud_list[i]; ++ if (baudrate == 0) { ++ tty_encode_baud_rate(tty, 0, 0); ++ return; ++ } ++ ++ idx = f81232_find_clk(baudrate); + if (idx >= 0) { +- baudrate = baud_list[i]; + tty_encode_baud_rate(tty, baudrate, baudrate); + break; + } +diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c +index ddfcd72eb0ae7..4083ae961be43 100644 +--- a/drivers/usb/serial/f81534.c ++++ b/drivers/usb/serial/f81534.c +@@ -536,9 +536,6 @@ static int f81534_submit_writer(struct usb_serial_port *port, gfp_t mem_flags) + + static u32 f81534_calc_baud_divisor(u32 baudrate, u32 clockrate) + { +- if (!baudrate) +- return 0; +- + /* Round to nearest divisor */ + return DIV_ROUND_CLOSEST(clockrate, baudrate); + } +@@ -568,9 +565,14 @@ static int f81534_set_port_config(struct usb_serial_port *port, + u32 baud_list[] = {baudrate, old_baudrate, F81534_DEFAULT_BAUD_RATE}; + + for (i = 0; i < ARRAY_SIZE(baud_list); ++i) { +- idx = f81534_find_clk(baud_list[i]); ++ baudrate = baud_list[i]; ++ if (baudrate == 0) { ++ tty_encode_baud_rate(tty, 0, 0); ++ return 0; ++ } ++ ++ idx = f81534_find_clk(baudrate); + if (idx >= 0) { +- baudrate = baud_list[i]; + tty_encode_baud_rate(tty, baudrate, baudrate); + break; + } +diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c +index c3b7f1d98e781..dee79c7d82d5c 100644 +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -255,6 +255,7 @@ static void option_instat_callback(struct urb *urb); + #define QUECTEL_PRODUCT_EP06 0x0306 + #define QUECTEL_PRODUCT_EM05G 0x030a + #define QUECTEL_PRODUCT_EM060K 0x030b ++#define QUECTEL_PRODUCT_EM05G_SG 0x0311 + #define QUECTEL_PRODUCT_EM12 0x0512 + #define QUECTEL_PRODUCT_RM500Q 0x0800 + #define QUECTEL_PRODUCT_RM520N 0x0801 +@@ -1160,6 +1161,8 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) }, + { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G, 0xff), + .driver_info = RSVD(6) | ZLP }, ++ { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G_SG, 0xff), ++ .driver_info = RSVD(6) | ZLP }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0x00, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0xff, 0x30) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0xff, 0x40) }, +diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c +index 747be69e5e699..5e912dd29b4c9 100644 +--- a/drivers/usb/storage/alauda.c ++++ b/drivers/usb/storage/alauda.c +@@ -438,6 +438,8 @@ static int alauda_init_media(struct us_data *us) + + MEDIA_INFO(us).blockshift + MEDIA_INFO(us).pageshift); + MEDIA_INFO(us).pba_to_lba = kcalloc(num_zones, sizeof(u16*), GFP_NOIO); + MEDIA_INFO(us).lba_to_pba = kcalloc(num_zones, sizeof(u16*), GFP_NOIO); ++ if (MEDIA_INFO(us).pba_to_lba == NULL || MEDIA_INFO(us).lba_to_pba == NULL) ++ return USB_STOR_TRANSPORT_ERROR; + + if (alauda_reset_media(us) != USB_STOR_XFER_GOOD) + return USB_STOR_TRANSPORT_ERROR; +diff --git a/drivers/usb/typec/bus.c b/drivers/usb/typec/bus.c +index 26ea2fdec17dc..31c2a3130cadb 100644 +--- a/drivers/usb/typec/bus.c ++++ b/drivers/usb/typec/bus.c +@@ -134,7 +134,7 @@ int typec_altmode_exit(struct typec_altmode *adev) + if (!adev || !adev->active) + return 0; + +- if (!pdev->ops || !pdev->ops->enter) ++ if (!pdev->ops || !pdev->ops->exit) + return -EOPNOTSUPP; + + /* Moving to USB Safe State */ +diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c +index b2bfcebe218f0..72f8d1e876004 100644 +--- a/drivers/usb/typec/tcpm/tcpci.c ++++ b/drivers/usb/typec/tcpm/tcpci.c +@@ -794,8 +794,10 @@ struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data) + return ERR_PTR(err); + + tcpci->port = tcpm_register_port(tcpci->dev, &tcpci->tcpc); +- if (IS_ERR(tcpci->port)) ++ if (IS_ERR(tcpci->port)) { ++ fwnode_handle_put(tcpci->tcpc.fwnode); + return ERR_CAST(tcpci->port); ++ } + + return tcpci; + } +@@ -804,6 +806,7 @@ EXPORT_SYMBOL_GPL(tcpci_register_port); + void tcpci_unregister_port(struct tcpci *tcpci) + { + tcpm_unregister_port(tcpci->port); ++ fwnode_handle_put(tcpci->tcpc.fwnode); + } + EXPORT_SYMBOL_GPL(tcpci_unregister_port); + +diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c +index 2a77bab948f54..195c9c16f817f 100644 +--- a/drivers/usb/typec/tipd/core.c ++++ b/drivers/usb/typec/tipd/core.c +@@ -814,20 +814,19 @@ static int tps6598x_probe(struct i2c_client *client) + + ret = devm_tps6598_psy_register(tps); + if (ret) +- return ret; ++ goto err_role_put; + + tps->port = typec_register_port(&client->dev, &typec_cap); + if (IS_ERR(tps->port)) { + ret = PTR_ERR(tps->port); + goto err_role_put; + } +- fwnode_handle_put(fwnode); + + if (status & TPS_STATUS_PLUG_PRESENT) { + ret = tps6598x_read16(tps, TPS_REG_POWER_STATUS, &tps->pwr_status); + if (ret < 0) { + dev_err(tps->dev, "failed to read power status: %d\n", ret); +- goto err_role_put; ++ goto err_unregister_port; + } + ret = tps6598x_connect(tps, status); + if (ret) +@@ -840,14 +839,16 @@ static int tps6598x_probe(struct i2c_client *client) + dev_name(&client->dev), tps); + if (ret) { + tps6598x_disconnect(tps, 0); +- typec_unregister_port(tps->port); +- goto err_role_put; ++ goto err_unregister_port; + } + + i2c_set_clientdata(client, tps); ++ fwnode_handle_put(fwnode); + + return 0; + ++err_unregister_port: ++ typec_unregister_port(tps->port); + err_role_put: + usb_role_switch_put(tps->role_sw); + err_fwnode_put: +diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c +index a7987fc764cc6..eabe519013e78 100644 +--- a/drivers/usb/typec/ucsi/ucsi.c ++++ b/drivers/usb/typec/ucsi/ucsi.c +@@ -1270,8 +1270,9 @@ err: + return ret; + } + +-int ucsi_resume(struct ucsi *ucsi) ++static void ucsi_resume_work(struct work_struct *work) + { ++ struct ucsi *ucsi = container_of(work, struct ucsi, resume_work); + struct ucsi_connector *con; + u64 command; + int ret; +@@ -1279,15 +1280,21 @@ int ucsi_resume(struct ucsi *ucsi) + /* Restore UCSI notification enable mask after system resume */ + command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy; + ret = ucsi_send_command(ucsi, command, NULL, 0); +- if (ret < 0) +- return ret; ++ if (ret < 0) { ++ dev_err(ucsi->dev, "failed to re-enable notifications (%d)\n", ret); ++ return; ++ } + + for (con = ucsi->connector; con->port; con++) { + mutex_lock(&con->lock); +- ucsi_check_connection(con); ++ ucsi_partner_task(con, ucsi_check_connection, 1, 0); + mutex_unlock(&con->lock); + } ++} + ++int ucsi_resume(struct ucsi *ucsi) ++{ ++ queue_work(system_long_wq, &ucsi->resume_work); + return 0; + } + EXPORT_SYMBOL_GPL(ucsi_resume); +@@ -1347,6 +1354,7 @@ struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops) + if (!ucsi) + return ERR_PTR(-ENOMEM); + ++ INIT_WORK(&ucsi->resume_work, ucsi_resume_work); + INIT_DELAYED_WORK(&ucsi->work, ucsi_init_work); + mutex_init(&ucsi->ppm_lock); + ucsi->dev = dev; +@@ -1401,6 +1409,7 @@ void ucsi_unregister(struct ucsi *ucsi) + + /* Make sure that we are not in the middle of driver initialization */ + cancel_delayed_work_sync(&ucsi->work); ++ cancel_work_sync(&ucsi->resume_work); + + /* Disable notifications */ + ucsi->ops->async_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd)); +diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h +index 8eb391e3e592c..c968474ee5473 100644 +--- a/drivers/usb/typec/ucsi/ucsi.h ++++ b/drivers/usb/typec/ucsi/ucsi.h +@@ -287,6 +287,7 @@ struct ucsi { + struct ucsi_capability cap; + struct ucsi_connector *connector; + ++ struct work_struct resume_work; + struct delayed_work work; + int work_count; + #define UCSI_ROLE_SWITCH_RETRY_PER_HZ 10 +diff --git a/drivers/usb/typec/wusb3801.c b/drivers/usb/typec/wusb3801.c +index 3cc7a15ecbd31..a43a18d4b02ed 100644 +--- a/drivers/usb/typec/wusb3801.c ++++ b/drivers/usb/typec/wusb3801.c +@@ -364,7 +364,7 @@ static int wusb3801_probe(struct i2c_client *client) + /* Initialize the hardware with the devicetree settings. */ + ret = wusb3801_hw_init(wusb3801); + if (ret) +- return ret; ++ goto err_put_connector; + + wusb3801->cap.revision = USB_TYPEC_REV_1_2; + wusb3801->cap.accessory[0] = TYPEC_ACCESSORY_AUDIO; +diff --git a/drivers/vfio/iova_bitmap.c b/drivers/vfio/iova_bitmap.c +index 6631e8befe1b2..0f19d502f351b 100644 +--- a/drivers/vfio/iova_bitmap.c ++++ b/drivers/vfio/iova_bitmap.c +@@ -295,11 +295,13 @@ void iova_bitmap_free(struct iova_bitmap *bitmap) + */ + static unsigned long iova_bitmap_mapped_remaining(struct iova_bitmap *bitmap) + { +- unsigned long remaining; ++ unsigned long remaining, bytes; ++ ++ bytes = (bitmap->mapped.npages << PAGE_SHIFT) - bitmap->mapped.pgoff; + + remaining = bitmap->mapped_total_index - bitmap->mapped_base_index; + remaining = min_t(unsigned long, remaining, +- (bitmap->mapped.npages << PAGE_SHIFT) / sizeof(*bitmap->bitmap)); ++ bytes / sizeof(*bitmap->bitmap)); + + return remaining; + } +@@ -394,29 +396,27 @@ int iova_bitmap_for_each(struct iova_bitmap *bitmap, void *opaque, + * Set the bits corresponding to the range [iova .. iova+length-1] in + * the user bitmap. + * +- * Return: The number of bits set. + */ + void iova_bitmap_set(struct iova_bitmap *bitmap, + unsigned long iova, size_t length) + { + struct iova_bitmap_map *mapped = &bitmap->mapped; +- unsigned long offset = (iova - mapped->iova) >> mapped->pgshift; +- unsigned long nbits = max_t(unsigned long, 1, length >> mapped->pgshift); +- unsigned long page_idx = offset / BITS_PER_PAGE; +- unsigned long page_offset = mapped->pgoff; +- void *kaddr; +- +- offset = offset % BITS_PER_PAGE; ++ unsigned long cur_bit = ((iova - mapped->iova) >> ++ mapped->pgshift) + mapped->pgoff * BITS_PER_BYTE; ++ unsigned long last_bit = (((iova + length - 1) - mapped->iova) >> ++ mapped->pgshift) + mapped->pgoff * BITS_PER_BYTE; + + do { +- unsigned long size = min(BITS_PER_PAGE - offset, nbits); ++ unsigned int page_idx = cur_bit / BITS_PER_PAGE; ++ unsigned int offset = cur_bit % BITS_PER_PAGE; ++ unsigned int nbits = min(BITS_PER_PAGE - offset, ++ last_bit - cur_bit + 1); ++ void *kaddr; + + kaddr = kmap_local_page(mapped->pages[page_idx]); +- bitmap_set(kaddr + page_offset, offset, size); ++ bitmap_set(kaddr, offset, nbits); + kunmap_local(kaddr); +- page_offset = offset = 0; +- nbits -= size; +- page_idx++; +- } while (nbits > 0); ++ cur_bit += nbits; ++ } while (cur_bit <= last_bit); + } + EXPORT_SYMBOL_GPL(iova_bitmap_set); +diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c +index 55dc4f43c31e3..1a0a238ffa354 100644 +--- a/drivers/vfio/platform/vfio_platform_common.c ++++ b/drivers/vfio/platform/vfio_platform_common.c +@@ -72,12 +72,11 @@ static int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev, + const char **extra_dbg) + { + #ifdef CONFIG_ACPI +- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct device *dev = vdev->device; + acpi_handle handle = ACPI_HANDLE(dev); + acpi_status acpi_ret; + +- acpi_ret = acpi_evaluate_object(handle, "_RST", NULL, &buffer); ++ acpi_ret = acpi_evaluate_object(handle, "_RST", NULL, NULL); + if (ACPI_FAILURE(acpi_ret)) { + if (extra_dbg) + *extra_dbg = acpi_format_exception(acpi_ret); +diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig +index cfc55273dc5d1..974e862cd20d6 100644 +--- a/drivers/video/fbdev/Kconfig ++++ b/drivers/video/fbdev/Kconfig +@@ -601,6 +601,7 @@ config FB_TGA + config FB_UVESA + tristate "Userspace VESA VGA graphics support" + depends on FB && CONNECTOR ++ depends on !UML + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT +@@ -2217,7 +2218,6 @@ config FB_SSD1307 + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_DEFERRED_IO +- select PWM + select FB_BACKLIGHT + help + This driver implements support for the Solomon SSD1307 +diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c +index c0143d38df83a..14a7d404062c3 100644 +--- a/drivers/video/fbdev/core/fbcon.c ++++ b/drivers/video/fbdev/core/fbcon.c +@@ -2450,7 +2450,8 @@ err_out: + + if (userfont) { + p->userfont = old_userfont; +- REFCOUNT(data)--; ++ if (--REFCOUNT(data) == 0) ++ kfree(data - FONT_EXTRA_WORDS * sizeof(int)); + } + + vc->vc_font.width = old_width; +diff --git a/drivers/video/fbdev/ep93xx-fb.c b/drivers/video/fbdev/ep93xx-fb.c +index 2398b3d48fedf..305f1587bd898 100644 +--- a/drivers/video/fbdev/ep93xx-fb.c ++++ b/drivers/video/fbdev/ep93xx-fb.c +@@ -552,12 +552,14 @@ static int ep93xxfb_probe(struct platform_device *pdev) + + err = register_framebuffer(info); + if (err) +- goto failed_check; ++ goto failed_framebuffer; + + dev_info(info->dev, "registered. Mode = %dx%d-%d\n", + info->var.xres, info->var.yres, info->var.bits_per_pixel); + return 0; + ++failed_framebuffer: ++ clk_disable_unprepare(fbi->clk); + failed_check: + if (fbi->mach_info->teardown) + fbi->mach_info->teardown(pdev); +diff --git a/drivers/video/fbdev/geode/Kconfig b/drivers/video/fbdev/geode/Kconfig +index ac9c860592aaf..85bc14b6faf64 100644 +--- a/drivers/video/fbdev/geode/Kconfig ++++ b/drivers/video/fbdev/geode/Kconfig +@@ -5,6 +5,7 @@ + config FB_GEODE + bool "AMD Geode family framebuffer support" + depends on FB && PCI && (X86_32 || (X86 && COMPILE_TEST)) ++ depends on !UML + help + Say 'Y' here to allow you to select framebuffer drivers for + the AMD Geode family of processors. +diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c +index 072ce07ba9e05..4ff25dfc865d9 100644 +--- a/drivers/video/fbdev/hyperv_fb.c ++++ b/drivers/video/fbdev/hyperv_fb.c +@@ -780,12 +780,18 @@ static void hvfb_ondemand_refresh_throttle(struct hvfb_par *par, + static int hvfb_on_panic(struct notifier_block *nb, + unsigned long e, void *p) + { ++ struct hv_device *hdev; + struct hvfb_par *par; + struct fb_info *info; + + par = container_of(nb, struct hvfb_par, hvfb_panic_nb); +- par->synchronous_fb = true; + info = par->info; ++ hdev = device_to_hv_device(info->device); ++ ++ if (hv_ringbuffer_spinlock_busy(hdev->channel)) ++ return NOTIFY_DONE; ++ ++ par->synchronous_fb = true; + if (par->need_docopy) + hvfb_docopy(par, 0, dio_fb_size); + synthvid_update(info, 0, 0, INT_MAX, INT_MAX); +diff --git a/drivers/video/fbdev/pm2fb.c b/drivers/video/fbdev/pm2fb.c +index 7da715d31a933..7a8609c40ae93 100644 +--- a/drivers/video/fbdev/pm2fb.c ++++ b/drivers/video/fbdev/pm2fb.c +@@ -1533,8 +1533,10 @@ static int pm2fb_probe(struct pci_dev *pdev, const struct pci_device_id *id) + } + + info = framebuffer_alloc(sizeof(struct pm2fb_par), &pdev->dev); +- if (!info) +- return -ENOMEM; ++ if (!info) { ++ err = -ENOMEM; ++ goto err_exit_disable; ++ } + default_par = info->par; + + switch (pdev->device) { +@@ -1715,6 +1717,8 @@ static int pm2fb_probe(struct pci_dev *pdev, const struct pci_device_id *id) + release_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len); + err_exit_neither: + framebuffer_release(info); ++ err_exit_disable: ++ pci_disable_device(pdev); + return retval; + } + +@@ -1739,6 +1743,7 @@ static void pm2fb_remove(struct pci_dev *pdev) + fb_dealloc_cmap(&info->cmap); + kfree(info->pixmap.addr); + framebuffer_release(info); ++ pci_disable_device(pdev); + } + + static const struct pci_device_id pm2fb_id_table[] = { +diff --git a/drivers/video/fbdev/uvesafb.c b/drivers/video/fbdev/uvesafb.c +index 00d789b6c0faf..0e3cabbec4b40 100644 +--- a/drivers/video/fbdev/uvesafb.c ++++ b/drivers/video/fbdev/uvesafb.c +@@ -1758,6 +1758,7 @@ static int uvesafb_probe(struct platform_device *dev) + out_unmap: + iounmap(info->screen_base); + out_mem: ++ arch_phys_wc_del(par->mtrr_handle); + release_mem_region(info->fix.smem_start, info->fix.smem_len); + out_reg: + release_region(0x3c0, 32); +diff --git a/drivers/video/fbdev/vermilion/vermilion.c b/drivers/video/fbdev/vermilion/vermilion.c +index 82b36dbb5b1a9..33051e3a2561e 100644 +--- a/drivers/video/fbdev/vermilion/vermilion.c ++++ b/drivers/video/fbdev/vermilion/vermilion.c +@@ -278,8 +278,10 @@ static int vmlfb_get_gpu(struct vml_par *par) + + mutex_unlock(&vml_mutex); + +- if (pci_enable_device(par->gpu) < 0) ++ if (pci_enable_device(par->gpu) < 0) { ++ pci_dev_put(par->gpu); + return -ENODEV; ++ } + + return 0; + } +diff --git a/drivers/video/fbdev/via/via-core.c b/drivers/video/fbdev/via/via-core.c +index 2ee8fcae08dfb..b8cd04defc5e2 100644 +--- a/drivers/video/fbdev/via/via-core.c ++++ b/drivers/video/fbdev/via/via-core.c +@@ -730,7 +730,14 @@ static int __init via_core_init(void) + return ret; + viafb_i2c_init(); + viafb_gpio_init(); +- return pci_register_driver(&via_driver); ++ ret = pci_register_driver(&via_driver); ++ if (ret) { ++ viafb_gpio_exit(); ++ viafb_i2c_exit(); ++ return ret; ++ } ++ ++ return 0; + } + + static void __exit via_core_exit(void) +diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c +index 1ea6d2e5b2187..99d6062afe72f 100644 +--- a/drivers/virt/coco/sev-guest/sev-guest.c ++++ b/drivers/virt/coco/sev-guest/sev-guest.c +@@ -800,3 +800,4 @@ MODULE_AUTHOR("Brijesh Singh <brijesh.singh@amd.com>"); + MODULE_LICENSE("GPL"); + MODULE_VERSION("1.0.0"); + MODULE_DESCRIPTION("AMD SEV Guest Driver"); ++MODULE_ALIAS("platform:sev-guest"); +diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c +index 34693f11385f6..e937b4dd28be7 100644 +--- a/drivers/watchdog/iTCO_wdt.c ++++ b/drivers/watchdog/iTCO_wdt.c +@@ -423,14 +423,18 @@ static unsigned int iTCO_wdt_get_timeleft(struct watchdog_device *wd_dev) + return time_left; + } + +-static void iTCO_wdt_set_running(struct iTCO_wdt_private *p) ++/* Returns true if the watchdog was running */ ++static bool iTCO_wdt_set_running(struct iTCO_wdt_private *p) + { + u16 val; + +- /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is * enabled */ ++ /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled */ + val = inw(TCO1_CNT(p)); +- if (!(val & BIT(11))) ++ if (!(val & BIT(11))) { + set_bit(WDOG_HW_RUNNING, &p->wddev.status); ++ return true; ++ } ++ return false; + } + + /* +@@ -518,9 +522,6 @@ static int iTCO_wdt_probe(struct platform_device *pdev) + return -ENODEV; /* Cannot reset NO_REBOOT bit */ + } + +- /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ +- p->update_no_reboot_bit(p->no_reboot_priv, true); +- + if (turn_SMI_watchdog_clear_off >= p->iTCO_version) { + /* + * Bit 13: TCO_EN -> 0 +@@ -572,7 +573,13 @@ static int iTCO_wdt_probe(struct platform_device *pdev) + watchdog_set_drvdata(&p->wddev, p); + platform_set_drvdata(pdev, p); + +- iTCO_wdt_set_running(p); ++ if (!iTCO_wdt_set_running(p)) { ++ /* ++ * If the watchdog was not running set NO_REBOOT now to ++ * prevent later reboots. ++ */ ++ p->update_no_reboot_bit(p->no_reboot_priv, true); ++ } + + /* Check that the heartbeat value is within it's range; + if not reset to the default */ +diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c +index fae50a24630bd..1edf45ee9890d 100644 +--- a/drivers/xen/privcmd.c ++++ b/drivers/xen/privcmd.c +@@ -760,7 +760,7 @@ static long privcmd_ioctl_mmap_resource(struct file *file, + goto out; + } + +- pfns = kcalloc(kdata.num, sizeof(*pfns), GFP_KERNEL); ++ pfns = kcalloc(kdata.num, sizeof(*pfns), GFP_KERNEL | __GFP_NOWARN); + if (!pfns) { + rc = -ENOMEM; + goto out; +diff --git a/fs/afs/fs_probe.c b/fs/afs/fs_probe.c +index 3ac5fcf98d0d6..daaf3810cc925 100644 +--- a/fs/afs/fs_probe.c ++++ b/fs/afs/fs_probe.c +@@ -366,12 +366,15 @@ void afs_fs_probe_dispatcher(struct work_struct *work) + unsigned long nowj, timer_at, poll_at; + bool first_pass = true, set_timer = false; + +- if (!net->live) ++ if (!net->live) { ++ afs_dec_servers_outstanding(net); + return; ++ } + + _enter(""); + + if (list_empty(&net->fs_probe_fast) && list_empty(&net->fs_probe_slow)) { ++ afs_dec_servers_outstanding(net); + _leave(" [none]"); + return; + } +diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c +index 08d0c8797828c..9ce5e1f41c26f 100644 +--- a/fs/binfmt_elf_fdpic.c ++++ b/fs/binfmt_elf_fdpic.c +@@ -434,8 +434,9 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm) + current->mm->start_stack = current->mm->start_brk + stack_size; + #endif + +- if (create_elf_fdpic_tables(bprm, current->mm, +- &exec_params, &interp_params) < 0) ++ retval = create_elf_fdpic_tables(bprm, current->mm, &exec_params, ++ &interp_params); ++ if (retval < 0) + goto error; + + kdebug("- start_code %lx", current->mm->start_code); +diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c +index e1eae7ea823ae..bb202ad369d53 100644 +--- a/fs/binfmt_misc.c ++++ b/fs/binfmt_misc.c +@@ -44,10 +44,10 @@ static LIST_HEAD(entries); + static int enabled = 1; + + enum {Enabled, Magic}; +-#define MISC_FMT_PRESERVE_ARGV0 (1 << 31) +-#define MISC_FMT_OPEN_BINARY (1 << 30) +-#define MISC_FMT_CREDENTIALS (1 << 29) +-#define MISC_FMT_OPEN_FILE (1 << 28) ++#define MISC_FMT_PRESERVE_ARGV0 (1UL << 31) ++#define MISC_FMT_OPEN_BINARY (1UL << 30) ++#define MISC_FMT_CREDENTIALS (1UL << 29) ++#define MISC_FMT_OPEN_FILE (1UL << 28) + + typedef struct { + struct list_head list; +diff --git a/fs/btrfs/extent-io-tree.c b/fs/btrfs/extent-io-tree.c +index 83cb0378096f2..3676580c2d97e 100644 +--- a/fs/btrfs/extent-io-tree.c ++++ b/fs/btrfs/extent-io-tree.c +@@ -572,7 +572,7 @@ int __clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, + if (bits & (EXTENT_LOCKED | EXTENT_BOUNDARY)) + clear = 1; + again: +- if (!prealloc && gfpflags_allow_blocking(mask)) { ++ if (!prealloc) { + /* + * Don't care for allocation failure here because we might end + * up not needing the pre-allocated extent state at all, which +@@ -636,7 +636,8 @@ hit_next: + + if (state->start < start) { + prealloc = alloc_extent_state_atomic(prealloc); +- BUG_ON(!prealloc); ++ if (!prealloc) ++ goto search_again; + err = split_state(tree, state, prealloc, start); + if (err) + extent_io_tree_panic(tree, err); +@@ -657,7 +658,8 @@ hit_next: + */ + if (state->start <= end && state->end > end) { + prealloc = alloc_extent_state_atomic(prealloc); +- BUG_ON(!prealloc); ++ if (!prealloc) ++ goto search_again; + err = split_state(tree, state, prealloc, end + 1); + if (err) + extent_io_tree_panic(tree, err); +@@ -966,7 +968,7 @@ static int __set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, + else + ASSERT(failed_start == NULL); + again: +- if (!prealloc && gfpflags_allow_blocking(mask)) { ++ if (!prealloc) { + /* + * Don't care for allocation failure here because we might end + * up not needing the pre-allocated extent state at all, which +@@ -991,7 +993,8 @@ again: + state = tree_search_for_insert(tree, start, &p, &parent); + if (!state) { + prealloc = alloc_extent_state_atomic(prealloc); +- BUG_ON(!prealloc); ++ if (!prealloc) ++ goto search_again; + prealloc->start = start; + prealloc->end = end; + insert_state_fast(tree, prealloc, p, parent, bits, changeset); +@@ -1062,7 +1065,8 @@ hit_next: + } + + prealloc = alloc_extent_state_atomic(prealloc); +- BUG_ON(!prealloc); ++ if (!prealloc) ++ goto search_again; + err = split_state(tree, state, prealloc, start); + if (err) + extent_io_tree_panic(tree, err); +@@ -1099,7 +1103,8 @@ hit_next: + this_end = last_start - 1; + + prealloc = alloc_extent_state_atomic(prealloc); +- BUG_ON(!prealloc); ++ if (!prealloc) ++ goto search_again; + + /* + * Avoid to free 'prealloc' if it can be merged with the later +@@ -1130,7 +1135,8 @@ hit_next: + } + + prealloc = alloc_extent_state_atomic(prealloc); +- BUG_ON(!prealloc); ++ if (!prealloc) ++ goto search_again; + err = split_state(tree, state, prealloc, end + 1); + if (err) + extent_io_tree_panic(tree, err); +diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c +index d01631d478067..ed4e1c3705d0a 100644 +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -696,7 +696,10 @@ next_slot: + args->start - extent_offset, + 0, false); + ret = btrfs_inc_extent_ref(trans, &ref); +- BUG_ON(ret); /* -ENOMEM */ ++ if (ret) { ++ btrfs_abort_transaction(trans, ret); ++ break; ++ } + } + key.offset = args->start; + } +@@ -783,7 +786,10 @@ delete_extent_item: + key.offset - extent_offset, 0, + false); + ret = btrfs_free_extent(trans, &ref); +- BUG_ON(ret); /* -ENOMEM */ ++ if (ret) { ++ btrfs_abort_transaction(trans, ret); ++ break; ++ } + args->bytes_found += extent_end - key.offset; + } + +diff --git a/fs/char_dev.c b/fs/char_dev.c +index ba0ded7842a77..3f667292608c0 100644 +--- a/fs/char_dev.c ++++ b/fs/char_dev.c +@@ -547,7 +547,7 @@ int cdev_device_add(struct cdev *cdev, struct device *dev) + } + + rc = device_add(dev); +- if (rc) ++ if (rc && dev->devt) + cdev_del(cdev); + + return rc; +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index 1420acf987f03..157d3c0e3cc76 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -13,6 +13,8 @@ + #include <linux/in6.h> + #include <linux/inet.h> + #include <linux/slab.h> ++#include <linux/scatterlist.h> ++#include <linux/mm.h> + #include <linux/mempool.h> + #include <linux/workqueue.h> + #include <linux/utsname.h> +@@ -2137,4 +2139,70 @@ static inline void move_cifs_info_to_smb2(struct smb2_file_all_info *dst, const + dst->FileNameLength = src->FileNameLength; + } + ++static inline unsigned int cifs_get_num_sgs(const struct smb_rqst *rqst, ++ int num_rqst, ++ const u8 *sig) ++{ ++ unsigned int len, skip; ++ unsigned int nents = 0; ++ unsigned long addr; ++ int i, j; ++ ++ /* Assumes the first rqst has a transform header as the first iov. ++ * I.e. ++ * rqst[0].rq_iov[0] is transform header ++ * rqst[0].rq_iov[1+] data to be encrypted/decrypted ++ * rqst[1+].rq_iov[0+] data to be encrypted/decrypted ++ */ ++ for (i = 0; i < num_rqst; i++) { ++ /* ++ * The first rqst has a transform header where the ++ * first 20 bytes are not part of the encrypted blob. ++ */ ++ for (j = 0; j < rqst[i].rq_nvec; j++) { ++ struct kvec *iov = &rqst[i].rq_iov[j]; ++ ++ skip = (i == 0) && (j == 0) ? 20 : 0; ++ addr = (unsigned long)iov->iov_base + skip; ++ if (unlikely(is_vmalloc_addr((void *)addr))) { ++ len = iov->iov_len - skip; ++ nents += DIV_ROUND_UP(offset_in_page(addr) + len, ++ PAGE_SIZE); ++ } else { ++ nents++; ++ } ++ } ++ nents += rqst[i].rq_npages; ++ } ++ nents += DIV_ROUND_UP(offset_in_page(sig) + SMB2_SIGNATURE_SIZE, PAGE_SIZE); ++ return nents; ++} ++ ++/* We can not use the normal sg_set_buf() as we will sometimes pass a ++ * stack object as buf. ++ */ ++static inline struct scatterlist *cifs_sg_set_buf(struct scatterlist *sg, ++ const void *buf, ++ unsigned int buflen) ++{ ++ unsigned long addr = (unsigned long)buf; ++ unsigned int off = offset_in_page(addr); ++ ++ addr &= PAGE_MASK; ++ if (unlikely(is_vmalloc_addr((void *)addr))) { ++ do { ++ unsigned int len = min_t(unsigned int, buflen, PAGE_SIZE - off); ++ ++ sg_set_page(sg++, vmalloc_to_page((void *)addr), len, off); ++ ++ off = 0; ++ addr += PAGE_SIZE; ++ buflen -= len; ++ } while (buflen); ++ } else { ++ sg_set_page(sg++, virt_to_page(addr), buflen, off); ++ } ++ return sg; ++} ++ + #endif /* _CIFS_GLOB_H */ +diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h +index 83e83d8beabba..eb1a0de9dd553 100644 +--- a/fs/cifs/cifsproto.h ++++ b/fs/cifs/cifsproto.h +@@ -600,8 +600,8 @@ int setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw); + int cifs_alloc_hash(const char *name, struct shash_desc **sdesc); + void cifs_free_hash(struct shash_desc **sdesc); + +-extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page, +- unsigned int *len, unsigned int *offset); ++void rqst_page_get_length(const struct smb_rqst *rqst, unsigned int page, ++ unsigned int *len, unsigned int *offset); + struct cifs_chan * + cifs_ses_find_chan(struct cifs_ses *ses, struct TCP_Server_Info *server); + int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses); +diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c +index 3e68d8208cf5e..1cbecd64d697f 100644 +--- a/fs/cifs/misc.c ++++ b/fs/cifs/misc.c +@@ -1136,8 +1136,8 @@ cifs_free_hash(struct shash_desc **sdesc) + * @len: Where to store the length for this page: + * @offset: Where to store the offset for this page + */ +-void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page, +- unsigned int *len, unsigned int *offset) ++void rqst_page_get_length(const struct smb_rqst *rqst, unsigned int page, ++ unsigned int *len, unsigned int *offset) + { + *len = rqst->rq_pagesz; + *offset = (page == 0) ? rqst->rq_offset : 0; +diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c +index ffbd9a99fc128..ba6cc50af390f 100644 +--- a/fs/cifs/smb2file.c ++++ b/fs/cifs/smb2file.c +@@ -122,8 +122,8 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 + struct smb2_hdr *hdr = err_iov.iov_base; + + if (unlikely(!err_iov.iov_base || err_buftype == CIFS_NO_BUFFER)) +- rc = -ENOMEM; +- else if (hdr->Status == STATUS_STOPPED_ON_SYMLINK) { ++ goto out; ++ if (hdr->Status == STATUS_STOPPED_ON_SYMLINK) { + rc = smb2_parse_symlink_response(oparms->cifs_sb, &err_iov, + &data->symlink_target); + if (!rc) { +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index bfaafd02fb1f2..b24e68b5ccd61 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -4204,69 +4204,82 @@ fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len, + memcpy(&tr_hdr->SessionId, &shdr->SessionId, 8); + } + +-/* We can not use the normal sg_set_buf() as we will sometimes pass a +- * stack object as buf. +- */ +-static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf, +- unsigned int buflen) ++static void *smb2_aead_req_alloc(struct crypto_aead *tfm, const struct smb_rqst *rqst, ++ int num_rqst, const u8 *sig, u8 **iv, ++ struct aead_request **req, struct scatterlist **sgl, ++ unsigned int *num_sgs) + { +- void *addr; +- /* +- * VMAP_STACK (at least) puts stack into the vmalloc address space +- */ +- if (is_vmalloc_addr(buf)) +- addr = vmalloc_to_page(buf); +- else +- addr = virt_to_page(buf); +- sg_set_page(sg, addr, buflen, offset_in_page(buf)); ++ unsigned int req_size = sizeof(**req) + crypto_aead_reqsize(tfm); ++ unsigned int iv_size = crypto_aead_ivsize(tfm); ++ unsigned int len; ++ u8 *p; ++ ++ *num_sgs = cifs_get_num_sgs(rqst, num_rqst, sig); ++ ++ len = iv_size; ++ len += crypto_aead_alignmask(tfm) & ~(crypto_tfm_ctx_alignment() - 1); ++ len = ALIGN(len, crypto_tfm_ctx_alignment()); ++ len += req_size; ++ len = ALIGN(len, __alignof__(struct scatterlist)); ++ len += *num_sgs * sizeof(**sgl); ++ ++ p = kmalloc(len, GFP_ATOMIC); ++ if (!p) ++ return NULL; ++ ++ *iv = (u8 *)PTR_ALIGN(p, crypto_aead_alignmask(tfm) + 1); ++ *req = (struct aead_request *)PTR_ALIGN(*iv + iv_size, ++ crypto_tfm_ctx_alignment()); ++ *sgl = (struct scatterlist *)PTR_ALIGN((u8 *)*req + req_size, ++ __alignof__(struct scatterlist)); ++ return p; + } + +-/* Assumes the first rqst has a transform header as the first iov. +- * I.e. +- * rqst[0].rq_iov[0] is transform header +- * rqst[0].rq_iov[1+] data to be encrypted/decrypted +- * rqst[1+].rq_iov[0+] data to be encrypted/decrypted +- */ +-static struct scatterlist * +-init_sg(int num_rqst, struct smb_rqst *rqst, u8 *sign) ++static void *smb2_get_aead_req(struct crypto_aead *tfm, const struct smb_rqst *rqst, ++ int num_rqst, const u8 *sig, u8 **iv, ++ struct aead_request **req, struct scatterlist **sgl) + { +- unsigned int sg_len; ++ unsigned int off, len, skip; + struct scatterlist *sg; +- unsigned int i; +- unsigned int j; +- unsigned int idx = 0; +- int skip; +- +- sg_len = 1; +- for (i = 0; i < num_rqst; i++) +- sg_len += rqst[i].rq_nvec + rqst[i].rq_npages; ++ unsigned int num_sgs; ++ unsigned long addr; ++ int i, j; ++ void *p; + +- sg = kmalloc_array(sg_len, sizeof(struct scatterlist), GFP_KERNEL); +- if (!sg) ++ p = smb2_aead_req_alloc(tfm, rqst, num_rqst, sig, iv, req, sgl, &num_sgs); ++ if (!p) + return NULL; + +- sg_init_table(sg, sg_len); ++ sg_init_table(*sgl, num_sgs); ++ sg = *sgl; ++ ++ /* Assumes the first rqst has a transform header as the first iov. ++ * I.e. ++ * rqst[0].rq_iov[0] is transform header ++ * rqst[0].rq_iov[1+] data to be encrypted/decrypted ++ * rqst[1+].rq_iov[0+] data to be encrypted/decrypted ++ */ + for (i = 0; i < num_rqst; i++) { ++ /* ++ * The first rqst has a transform header where the ++ * first 20 bytes are not part of the encrypted blob. ++ */ + for (j = 0; j < rqst[i].rq_nvec; j++) { +- /* +- * The first rqst has a transform header where the +- * first 20 bytes are not part of the encrypted blob +- */ +- skip = (i == 0) && (j == 0) ? 20 : 0; +- smb2_sg_set_buf(&sg[idx++], +- rqst[i].rq_iov[j].iov_base + skip, +- rqst[i].rq_iov[j].iov_len - skip); +- } ++ struct kvec *iov = &rqst[i].rq_iov[j]; + ++ skip = (i == 0) && (j == 0) ? 20 : 0; ++ addr = (unsigned long)iov->iov_base + skip; ++ len = iov->iov_len - skip; ++ sg = cifs_sg_set_buf(sg, (void *)addr, len); ++ } + for (j = 0; j < rqst[i].rq_npages; j++) { +- unsigned int len, offset; +- +- rqst_page_get_length(&rqst[i], j, &len, &offset); +- sg_set_page(&sg[idx++], rqst[i].rq_pages[j], len, offset); ++ rqst_page_get_length(&rqst[i], j, &len, &off); ++ sg_set_page(sg++, rqst[i].rq_pages[j], len, off); + } + } +- smb2_sg_set_buf(&sg[idx], sign, SMB2_SIGNATURE_SIZE); +- return sg; ++ cifs_sg_set_buf(sg, sig, SMB2_SIGNATURE_SIZE); ++ ++ return p; + } + + static int +@@ -4314,11 +4327,11 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, + u8 sign[SMB2_SIGNATURE_SIZE] = {}; + u8 key[SMB3_ENC_DEC_KEY_SIZE]; + struct aead_request *req; +- char *iv; +- unsigned int iv_len; ++ u8 *iv; + DECLARE_CRYPTO_WAIT(wait); + struct crypto_aead *tfm; + unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize); ++ void *creq; + + rc = smb2_get_enc_key(server, le64_to_cpu(tr_hdr->SessionId), enc, key); + if (rc) { +@@ -4352,32 +4365,15 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, + return rc; + } + +- req = aead_request_alloc(tfm, GFP_KERNEL); +- if (!req) { +- cifs_server_dbg(VFS, "%s: Failed to alloc aead request\n", __func__); ++ creq = smb2_get_aead_req(tfm, rqst, num_rqst, sign, &iv, &req, &sg); ++ if (unlikely(!creq)) + return -ENOMEM; +- } + + if (!enc) { + memcpy(sign, &tr_hdr->Signature, SMB2_SIGNATURE_SIZE); + crypt_len += SMB2_SIGNATURE_SIZE; + } + +- sg = init_sg(num_rqst, rqst, sign); +- if (!sg) { +- cifs_server_dbg(VFS, "%s: Failed to init sg\n", __func__); +- rc = -ENOMEM; +- goto free_req; +- } +- +- iv_len = crypto_aead_ivsize(tfm); +- iv = kzalloc(iv_len, GFP_KERNEL); +- if (!iv) { +- cifs_server_dbg(VFS, "%s: Failed to alloc iv\n", __func__); +- rc = -ENOMEM; +- goto free_sg; +- } +- + if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) || + (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) + memcpy(iv, (char *)tr_hdr->Nonce, SMB3_AES_GCM_NONCE); +@@ -4386,6 +4382,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, + memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES_CCM_NONCE); + } + ++ aead_request_set_tfm(req, tfm); + aead_request_set_crypt(req, sg, sg, crypt_len, iv); + aead_request_set_ad(req, assoc_data_len); + +@@ -4398,11 +4395,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, + if (!rc && enc) + memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE); + +- kfree_sensitive(iv); +-free_sg: +- kfree_sensitive(sg); +-free_req: +- kfree_sensitive(req); ++ kfree_sensitive(creq); + return rc; + } + +diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c +index d1f9d26322027..ec6519e1ca3bf 100644 +--- a/fs/configfs/dir.c ++++ b/fs/configfs/dir.c +@@ -316,6 +316,7 @@ static int configfs_create_dir(struct config_item *item, struct dentry *dentry, + return 0; + + out_remove: ++ configfs_put(dentry->d_fsdata); + configfs_remove_dirent(dentry); + return PTR_ERR(inode); + } +@@ -382,6 +383,7 @@ int configfs_create_link(struct configfs_dirent *target, struct dentry *parent, + return 0; + + out_remove: ++ configfs_put(dentry->d_fsdata); + configfs_remove_dirent(dentry); + return PTR_ERR(inode); + } +diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c +index ddb3fc258df94..b54f470e0d031 100644 +--- a/fs/debugfs/file.c ++++ b/fs/debugfs/file.c +@@ -378,8 +378,8 @@ ssize_t debugfs_attr_read(struct file *file, char __user *buf, + } + EXPORT_SYMBOL_GPL(debugfs_attr_read); + +-ssize_t debugfs_attr_write(struct file *file, const char __user *buf, +- size_t len, loff_t *ppos) ++static ssize_t debugfs_attr_write_xsigned(struct file *file, const char __user *buf, ++ size_t len, loff_t *ppos, bool is_signed) + { + struct dentry *dentry = F_DENTRY(file); + ssize_t ret; +@@ -387,12 +387,28 @@ ssize_t debugfs_attr_write(struct file *file, const char __user *buf, + ret = debugfs_file_get(dentry); + if (unlikely(ret)) + return ret; +- ret = simple_attr_write(file, buf, len, ppos); ++ if (is_signed) ++ ret = simple_attr_write_signed(file, buf, len, ppos); ++ else ++ ret = simple_attr_write(file, buf, len, ppos); + debugfs_file_put(dentry); + return ret; + } ++ ++ssize_t debugfs_attr_write(struct file *file, const char __user *buf, ++ size_t len, loff_t *ppos) ++{ ++ return debugfs_attr_write_xsigned(file, buf, len, ppos, false); ++} + EXPORT_SYMBOL_GPL(debugfs_attr_write); + ++ssize_t debugfs_attr_write_signed(struct file *file, const char __user *buf, ++ size_t len, loff_t *ppos) ++{ ++ return debugfs_attr_write_xsigned(file, buf, len, ppos, true); ++} ++EXPORT_SYMBOL_GPL(debugfs_attr_write_signed); ++ + static struct dentry *debugfs_create_mode_unsafe(const char *name, umode_t mode, + struct dentry *parent, void *value, + const struct file_operations *fops, +@@ -738,11 +754,11 @@ static int debugfs_atomic_t_get(void *data, u64 *val) + *val = atomic_read((atomic_t *)data); + return 0; + } +-DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get, ++DEFINE_DEBUGFS_ATTRIBUTE_SIGNED(fops_atomic_t, debugfs_atomic_t_get, + debugfs_atomic_t_set, "%lld\n"); +-DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t_ro, debugfs_atomic_t_get, NULL, ++DEFINE_DEBUGFS_ATTRIBUTE_SIGNED(fops_atomic_t_ro, debugfs_atomic_t_get, NULL, + "%lld\n"); +-DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t_wo, NULL, debugfs_atomic_t_set, ++DEFINE_DEBUGFS_ATTRIBUTE_SIGNED(fops_atomic_t_wo, NULL, debugfs_atomic_t_set, + "%lld\n"); + + /** +diff --git a/fs/erofs/fscache.c b/fs/erofs/fscache.c +index af5ed6b9c54dd..6a792a513d6b8 100644 +--- a/fs/erofs/fscache.c ++++ b/fs/erofs/fscache.c +@@ -494,7 +494,8 @@ static int erofs_fscache_register_domain(struct super_block *sb) + + static + struct erofs_fscache *erofs_fscache_acquire_cookie(struct super_block *sb, +- char *name, bool need_inode) ++ char *name, ++ unsigned int flags) + { + struct fscache_volume *volume = EROFS_SB(sb)->volume; + struct erofs_fscache *ctx; +@@ -516,7 +517,7 @@ struct erofs_fscache *erofs_fscache_acquire_cookie(struct super_block *sb, + fscache_use_cookie(cookie, false); + ctx->cookie = cookie; + +- if (need_inode) { ++ if (flags & EROFS_REG_COOKIE_NEED_INODE) { + struct inode *const inode = new_inode(sb); + + if (!inode) { +@@ -554,14 +555,15 @@ static void erofs_fscache_relinquish_cookie(struct erofs_fscache *ctx) + + static + struct erofs_fscache *erofs_fscache_domain_init_cookie(struct super_block *sb, +- char *name, bool need_inode) ++ char *name, ++ unsigned int flags) + { + int err; + struct inode *inode; + struct erofs_fscache *ctx; + struct erofs_domain *domain = EROFS_SB(sb)->domain; + +- ctx = erofs_fscache_acquire_cookie(sb, name, need_inode); ++ ctx = erofs_fscache_acquire_cookie(sb, name, flags); + if (IS_ERR(ctx)) + return ctx; + +@@ -589,7 +591,8 @@ out: + + static + struct erofs_fscache *erofs_domain_register_cookie(struct super_block *sb, +- char *name, bool need_inode) ++ char *name, ++ unsigned int flags) + { + struct inode *inode; + struct erofs_fscache *ctx; +@@ -602,23 +605,30 @@ struct erofs_fscache *erofs_domain_register_cookie(struct super_block *sb, + ctx = inode->i_private; + if (!ctx || ctx->domain != domain || strcmp(ctx->name, name)) + continue; +- igrab(inode); ++ if (!(flags & EROFS_REG_COOKIE_NEED_NOEXIST)) { ++ igrab(inode); ++ } else { ++ erofs_err(sb, "%s already exists in domain %s", name, ++ domain->domain_id); ++ ctx = ERR_PTR(-EEXIST); ++ } + spin_unlock(&psb->s_inode_list_lock); + mutex_unlock(&erofs_domain_cookies_lock); + return ctx; + } + spin_unlock(&psb->s_inode_list_lock); +- ctx = erofs_fscache_domain_init_cookie(sb, name, need_inode); ++ ctx = erofs_fscache_domain_init_cookie(sb, name, flags); + mutex_unlock(&erofs_domain_cookies_lock); + return ctx; + } + + struct erofs_fscache *erofs_fscache_register_cookie(struct super_block *sb, +- char *name, bool need_inode) ++ char *name, ++ unsigned int flags) + { + if (EROFS_SB(sb)->domain_id) +- return erofs_domain_register_cookie(sb, name, need_inode); +- return erofs_fscache_acquire_cookie(sb, name, need_inode); ++ return erofs_domain_register_cookie(sb, name, flags); ++ return erofs_fscache_acquire_cookie(sb, name, flags); + } + + void erofs_fscache_unregister_cookie(struct erofs_fscache *ctx) +@@ -647,6 +657,7 @@ int erofs_fscache_register_fs(struct super_block *sb) + int ret; + struct erofs_sb_info *sbi = EROFS_SB(sb); + struct erofs_fscache *fscache; ++ unsigned int flags; + + if (sbi->domain_id) + ret = erofs_fscache_register_domain(sb); +@@ -655,8 +666,20 @@ int erofs_fscache_register_fs(struct super_block *sb) + if (ret) + return ret; + +- /* acquired domain/volume will be relinquished in kill_sb() on error */ +- fscache = erofs_fscache_register_cookie(sb, sbi->fsid, true); ++ /* ++ * When shared domain is enabled, using NEED_NOEXIST to guarantee ++ * the primary data blob (aka fsid) is unique in the shared domain. ++ * ++ * For non-shared-domain case, fscache_acquire_volume() invoked by ++ * erofs_fscache_register_volume() has already guaranteed ++ * the uniqueness of primary data blob. ++ * ++ * Acquired domain/volume will be relinquished in kill_sb() on error. ++ */ ++ flags = EROFS_REG_COOKIE_NEED_INODE; ++ if (sbi->domain_id) ++ flags |= EROFS_REG_COOKIE_NEED_NOEXIST; ++ fscache = erofs_fscache_register_cookie(sb, sbi->fsid, flags); + if (IS_ERR(fscache)) + return PTR_ERR(fscache); + +diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h +index 05dc686277220..e51f27b6bde15 100644 +--- a/fs/erofs/internal.h ++++ b/fs/erofs/internal.h +@@ -604,13 +604,18 @@ static inline int z_erofs_load_lzma_config(struct super_block *sb, + } + #endif /* !CONFIG_EROFS_FS_ZIP */ + ++/* flags for erofs_fscache_register_cookie() */ ++#define EROFS_REG_COOKIE_NEED_INODE 1 ++#define EROFS_REG_COOKIE_NEED_NOEXIST 2 ++ + /* fscache.c */ + #ifdef CONFIG_EROFS_FS_ONDEMAND + int erofs_fscache_register_fs(struct super_block *sb); + void erofs_fscache_unregister_fs(struct super_block *sb); + + struct erofs_fscache *erofs_fscache_register_cookie(struct super_block *sb, +- char *name, bool need_inode); ++ char *name, ++ unsigned int flags); + void erofs_fscache_unregister_cookie(struct erofs_fscache *fscache); + + extern const struct address_space_operations erofs_fscache_access_aops; +@@ -623,7 +628,8 @@ static inline void erofs_fscache_unregister_fs(struct super_block *sb) {} + + static inline + struct erofs_fscache *erofs_fscache_register_cookie(struct super_block *sb, +- char *name, bool need_inode) ++ char *name, ++ unsigned int flags) + { + return ERR_PTR(-EOPNOTSUPP); + } +diff --git a/fs/erofs/super.c b/fs/erofs/super.c +index 1c7dcca702b3e..481788c24a68b 100644 +--- a/fs/erofs/super.c ++++ b/fs/erofs/super.c +@@ -245,7 +245,7 @@ static int erofs_init_device(struct erofs_buf *buf, struct super_block *sb, + } + + if (erofs_is_fscache_mode(sb)) { +- fscache = erofs_fscache_register_cookie(sb, dif->path, false); ++ fscache = erofs_fscache_register_cookie(sb, dif->path, 0); + if (IS_ERR(fscache)) + return PTR_ERR(fscache); + dif->fscache = fscache; +diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c +index b792d424d774c..cf4871834ebb2 100644 +--- a/fs/erofs/zdata.c ++++ b/fs/erofs/zdata.c +@@ -488,7 +488,8 @@ static int z_erofs_register_pcluster(struct z_erofs_decompress_frontend *fe) + struct erofs_workgroup *grp; + int err; + +- if (!(map->m_flags & EROFS_MAP_ENCODED)) { ++ if (!(map->m_flags & EROFS_MAP_ENCODED) || ++ (!ztailpacking && !(map->m_pa >> PAGE_SHIFT))) { + DBG_BUGON(1); + return -EFSCORRUPTED; + } +diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c +index 0bb66927e3d06..e6d5d7a18fb06 100644 +--- a/fs/erofs/zmap.c ++++ b/fs/erofs/zmap.c +@@ -694,10 +694,15 @@ static int z_erofs_do_map_blocks(struct inode *inode, + map->m_pa = blknr_to_addr(m.pblk); + err = z_erofs_get_extent_compressedlen(&m, initial_lcn); + if (err) +- goto out; ++ goto unmap_out; + } + + if (m.headtype == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN) { ++ if (map->m_llen > map->m_plen) { ++ DBG_BUGON(1); ++ err = -EFSCORRUPTED; ++ goto unmap_out; ++ } + if (vi->z_advise & Z_EROFS_ADVISE_INTERLACED_PCLUSTER) + map->m_algorithmformat = + Z_EROFS_COMPRESSION_INTERLACED; +@@ -718,14 +723,12 @@ static int z_erofs_do_map_blocks(struct inode *inode, + if (!err) + map->m_flags |= EROFS_MAP_FULL_MAPPED; + } ++ + unmap_out: + erofs_unmap_metabuf(&m.map->buf); +- +-out: + erofs_dbg("%s, m_la %llu m_pa %llu m_llen %llu m_plen %llu m_flags 0%o", + __func__, map->m_la, map->m_pa, + map->m_llen, map->m_plen, map->m_flags); +- + return err; + } + +diff --git a/fs/eventfd.c b/fs/eventfd.c +index c0ffee99ad238..249ca6c0b7843 100644 +--- a/fs/eventfd.c ++++ b/fs/eventfd.c +@@ -43,21 +43,7 @@ struct eventfd_ctx { + int id; + }; + +-/** +- * eventfd_signal - Adds @n to the eventfd counter. +- * @ctx: [in] Pointer to the eventfd context. +- * @n: [in] Value of the counter to be added to the eventfd internal counter. +- * The value cannot be negative. +- * +- * This function is supposed to be called by the kernel in paths that do not +- * allow sleeping. In this function we allow the counter to reach the ULLONG_MAX +- * value, and we signal this as overflow condition by returning a EPOLLERR +- * to poll(2). +- * +- * Returns the amount by which the counter was incremented. This will be less +- * than @n if the counter has overflowed. +- */ +-__u64 eventfd_signal(struct eventfd_ctx *ctx, __u64 n) ++__u64 eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n, unsigned mask) + { + unsigned long flags; + +@@ -78,12 +64,31 @@ __u64 eventfd_signal(struct eventfd_ctx *ctx, __u64 n) + n = ULLONG_MAX - ctx->count; + ctx->count += n; + if (waitqueue_active(&ctx->wqh)) +- wake_up_locked_poll(&ctx->wqh, EPOLLIN); ++ wake_up_locked_poll(&ctx->wqh, EPOLLIN | mask); + current->in_eventfd = 0; + spin_unlock_irqrestore(&ctx->wqh.lock, flags); + + return n; + } ++ ++/** ++ * eventfd_signal - Adds @n to the eventfd counter. ++ * @ctx: [in] Pointer to the eventfd context. ++ * @n: [in] Value of the counter to be added to the eventfd internal counter. ++ * The value cannot be negative. ++ * ++ * This function is supposed to be called by the kernel in paths that do not ++ * allow sleeping. In this function we allow the counter to reach the ULLONG_MAX ++ * value, and we signal this as overflow condition by returning a EPOLLERR ++ * to poll(2). ++ * ++ * Returns the amount by which the counter was incremented. This will be less ++ * than @n if the counter has overflowed. ++ */ ++__u64 eventfd_signal(struct eventfd_ctx *ctx, __u64 n) ++{ ++ return eventfd_signal_mask(ctx, n, 0); ++} + EXPORT_SYMBOL_GPL(eventfd_signal); + + static void eventfd_free_ctx(struct eventfd_ctx *ctx) +diff --git a/fs/eventpoll.c b/fs/eventpoll.c +index 52954d4637b54..64659b1109733 100644 +--- a/fs/eventpoll.c ++++ b/fs/eventpoll.c +@@ -491,7 +491,8 @@ static inline void ep_set_busy_poll_napi_id(struct epitem *epi) + */ + #ifdef CONFIG_DEBUG_LOCK_ALLOC + +-static void ep_poll_safewake(struct eventpoll *ep, struct epitem *epi) ++static void ep_poll_safewake(struct eventpoll *ep, struct epitem *epi, ++ unsigned pollflags) + { + struct eventpoll *ep_src; + unsigned long flags; +@@ -522,16 +523,17 @@ static void ep_poll_safewake(struct eventpoll *ep, struct epitem *epi) + } + spin_lock_irqsave_nested(&ep->poll_wait.lock, flags, nests); + ep->nests = nests + 1; +- wake_up_locked_poll(&ep->poll_wait, EPOLLIN); ++ wake_up_locked_poll(&ep->poll_wait, EPOLLIN | pollflags); + ep->nests = 0; + spin_unlock_irqrestore(&ep->poll_wait.lock, flags); + } + + #else + +-static void ep_poll_safewake(struct eventpoll *ep, struct epitem *epi) ++static void ep_poll_safewake(struct eventpoll *ep, struct epitem *epi, ++ unsigned pollflags) + { +- wake_up_poll(&ep->poll_wait, EPOLLIN); ++ wake_up_poll(&ep->poll_wait, EPOLLIN | pollflags); + } + + #endif +@@ -742,7 +744,7 @@ static void ep_free(struct eventpoll *ep) + + /* We need to release all tasks waiting for these file */ + if (waitqueue_active(&ep->poll_wait)) +- ep_poll_safewake(ep, NULL); ++ ep_poll_safewake(ep, NULL, 0); + + /* + * We need to lock this because we could be hit by +@@ -1208,7 +1210,7 @@ out_unlock: + + /* We have to call this outside the lock */ + if (pwake) +- ep_poll_safewake(ep, epi); ++ ep_poll_safewake(ep, epi, pollflags & EPOLL_URING_WAKE); + + if (!(epi->event.events & EPOLLEXCLUSIVE)) + ewake = 1; +@@ -1553,7 +1555,7 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event, + + /* We have to call this outside the lock */ + if (pwake) +- ep_poll_safewake(ep, NULL); ++ ep_poll_safewake(ep, NULL, 0); + + return 0; + } +@@ -1629,7 +1631,7 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, + + /* We have to call this outside the lock */ + if (pwake) +- ep_poll_safewake(ep, NULL); ++ ep_poll_safewake(ep, NULL, 0); + + return 0; + } +diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c +index d315c2de136f2..74d3f2d2271f3 100644 +--- a/fs/f2fs/compress.c ++++ b/fs/f2fs/compress.c +@@ -346,7 +346,7 @@ static int zstd_init_compress_ctx(struct compress_ctx *cc) + if (!level) + level = F2FS_ZSTD_DEFAULT_CLEVEL; + +- params = zstd_get_params(F2FS_ZSTD_DEFAULT_CLEVEL, cc->rlen); ++ params = zstd_get_params(level, cc->rlen); + workspace_size = zstd_cstream_workspace_bound(¶ms.cParams); + + workspace = f2fs_kvmalloc(F2FS_I_SB(cc->inode), +diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h +index e6355a5683b75..8b9f0b3c77232 100644 +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -2974,7 +2974,7 @@ static inline void f2fs_change_bit(unsigned int nr, char *addr) + /* Flags that should be inherited by new inodes from their parent. */ + #define F2FS_FL_INHERITED (F2FS_SYNC_FL | F2FS_NODUMP_FL | F2FS_NOATIME_FL | \ + F2FS_DIRSYNC_FL | F2FS_PROJINHERIT_FL | \ +- F2FS_CASEFOLD_FL | F2FS_COMPR_FL | F2FS_NOCOMP_FL) ++ F2FS_CASEFOLD_FL) + + /* Flags that are appropriate for regular files (all but dir-specific ones). */ + #define F2FS_REG_FLMASK (~(F2FS_DIRSYNC_FL | F2FS_PROJINHERIT_FL | \ +diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c +index 82cda12582272..f96bbfa8b3991 100644 +--- a/fs/f2fs/file.c ++++ b/fs/f2fs/file.c +@@ -1915,6 +1915,10 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask) + if (!f2fs_disable_compressed_file(inode)) + return -EINVAL; + } else { ++ /* try to convert inline_data to support compression */ ++ int err = f2fs_convert_inline_inode(inode); ++ if (err) ++ return err; + if (!f2fs_may_compress(inode)) + return -EINVAL; + if (S_ISREG(inode->i_mode) && F2FS_HAS_BLOCKS(inode)) +diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c +index 4546e01b2ee08..b3184d8b1ce89 100644 +--- a/fs/f2fs/gc.c ++++ b/fs/f2fs/gc.c +@@ -96,16 +96,6 @@ static int gc_thread_func(void *data) + * invalidated soon after by user update or deletion. + * So, I'd like to wait some time to collect dirty segments. + */ +- if (sbi->gc_mode == GC_URGENT_HIGH) { +- spin_lock(&sbi->gc_urgent_high_lock); +- if (sbi->gc_urgent_high_remaining) { +- sbi->gc_urgent_high_remaining--; +- if (!sbi->gc_urgent_high_remaining) +- sbi->gc_mode = GC_NORMAL; +- } +- spin_unlock(&sbi->gc_urgent_high_lock); +- } +- + if (sbi->gc_mode == GC_URGENT_HIGH || + sbi->gc_mode == GC_URGENT_MID) { + wait_ms = gc_th->urgent_sleep_time; +@@ -162,6 +152,15 @@ do_gc: + /* balancing f2fs's metadata periodically */ + f2fs_balance_fs_bg(sbi, true); + next: ++ if (sbi->gc_mode == GC_URGENT_HIGH) { ++ spin_lock(&sbi->gc_urgent_high_lock); ++ if (sbi->gc_urgent_high_remaining) { ++ sbi->gc_urgent_high_remaining--; ++ if (!sbi->gc_urgent_high_remaining) ++ sbi->gc_mode = GC_NORMAL; ++ } ++ spin_unlock(&sbi->gc_urgent_high_lock); ++ } + sb_end_write(sbi->sb); + + } while (!kthread_should_stop()); +@@ -1110,6 +1109,7 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, + if (ofs_in_node >= max_addrs) { + f2fs_err(sbi, "Inconsistent ofs_in_node:%u in summary, ino:%u, nid:%u, max:%u", + ofs_in_node, dni->ino, dni->nid, max_addrs); ++ f2fs_put_page(node_page, 1); + return false; + } + +@@ -1744,8 +1744,9 @@ freed: + get_valid_blocks(sbi, segno, false) == 0) + seg_freed++; + +- if (__is_large_section(sbi) && segno + 1 < end_segno) +- sbi->next_victim_seg[gc_type] = segno + 1; ++ if (__is_large_section(sbi)) ++ sbi->next_victim_seg[gc_type] = ++ (segno + 1 < end_segno) ? segno + 1 : NULL_SEGNO; + skip: + f2fs_put_page(sum_page, 0); + } +@@ -2133,8 +2134,6 @@ out_unlock: + if (err) + return err; + +- set_sbi_flag(sbi, SBI_IS_RESIZEFS); +- + freeze_super(sbi->sb); + f2fs_down_write(&sbi->gc_lock); + f2fs_down_write(&sbi->cp_global_sem); +@@ -2150,6 +2149,7 @@ out_unlock: + if (err) + goto out_err; + ++ set_sbi_flag(sbi, SBI_IS_RESIZEFS); + err = free_segment_range(sbi, secs, false); + if (err) + goto recover_out; +@@ -2173,6 +2173,7 @@ out_unlock: + f2fs_commit_super(sbi, false); + } + recover_out: ++ clear_sbi_flag(sbi, SBI_IS_RESIZEFS); + if (err) { + set_sbi_flag(sbi, SBI_NEED_FSCK); + f2fs_err(sbi, "resize_fs failed, should run fsck to repair!"); +@@ -2185,6 +2186,5 @@ out_err: + f2fs_up_write(&sbi->cp_global_sem); + f2fs_up_write(&sbi->gc_lock); + thaw_super(sbi->sb); +- clear_sbi_flag(sbi, SBI_IS_RESIZEFS); + return err; + } +diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c +index a389772fd212a..b6c14c9c33a08 100644 +--- a/fs/f2fs/namei.c ++++ b/fs/f2fs/namei.c +@@ -22,8 +22,163 @@ + #include "acl.h" + #include <trace/events/f2fs.h> + ++static inline int is_extension_exist(const unsigned char *s, const char *sub, ++ bool tmp_ext) ++{ ++ size_t slen = strlen(s); ++ size_t sublen = strlen(sub); ++ int i; ++ ++ if (sublen == 1 && *sub == '*') ++ return 1; ++ ++ /* ++ * filename format of multimedia file should be defined as: ++ * "filename + '.' + extension + (optional: '.' + temp extension)". ++ */ ++ if (slen < sublen + 2) ++ return 0; ++ ++ if (!tmp_ext) { ++ /* file has no temp extension */ ++ if (s[slen - sublen - 1] != '.') ++ return 0; ++ return !strncasecmp(s + slen - sublen, sub, sublen); ++ } ++ ++ for (i = 1; i < slen - sublen; i++) { ++ if (s[i] != '.') ++ continue; ++ if (!strncasecmp(s + i + 1, sub, sublen)) ++ return 1; ++ } ++ ++ return 0; ++} ++ ++int f2fs_update_extension_list(struct f2fs_sb_info *sbi, const char *name, ++ bool hot, bool set) ++{ ++ __u8 (*extlist)[F2FS_EXTENSION_LEN] = sbi->raw_super->extension_list; ++ int cold_count = le32_to_cpu(sbi->raw_super->extension_count); ++ int hot_count = sbi->raw_super->hot_ext_count; ++ int total_count = cold_count + hot_count; ++ int start, count; ++ int i; ++ ++ if (set) { ++ if (total_count == F2FS_MAX_EXTENSION) ++ return -EINVAL; ++ } else { ++ if (!hot && !cold_count) ++ return -EINVAL; ++ if (hot && !hot_count) ++ return -EINVAL; ++ } ++ ++ if (hot) { ++ start = cold_count; ++ count = total_count; ++ } else { ++ start = 0; ++ count = cold_count; ++ } ++ ++ for (i = start; i < count; i++) { ++ if (strcmp(name, extlist[i])) ++ continue; ++ ++ if (set) ++ return -EINVAL; ++ ++ memcpy(extlist[i], extlist[i + 1], ++ F2FS_EXTENSION_LEN * (total_count - i - 1)); ++ memset(extlist[total_count - 1], 0, F2FS_EXTENSION_LEN); ++ if (hot) ++ sbi->raw_super->hot_ext_count = hot_count - 1; ++ else ++ sbi->raw_super->extension_count = ++ cpu_to_le32(cold_count - 1); ++ return 0; ++ } ++ ++ if (!set) ++ return -EINVAL; ++ ++ if (hot) { ++ memcpy(extlist[count], name, strlen(name)); ++ sbi->raw_super->hot_ext_count = hot_count + 1; ++ } else { ++ char buf[F2FS_MAX_EXTENSION][F2FS_EXTENSION_LEN]; ++ ++ memcpy(buf, &extlist[cold_count], ++ F2FS_EXTENSION_LEN * hot_count); ++ memset(extlist[cold_count], 0, F2FS_EXTENSION_LEN); ++ memcpy(extlist[cold_count], name, strlen(name)); ++ memcpy(&extlist[cold_count + 1], buf, ++ F2FS_EXTENSION_LEN * hot_count); ++ sbi->raw_super->extension_count = cpu_to_le32(cold_count + 1); ++ } ++ return 0; ++} ++ ++static void set_compress_new_inode(struct f2fs_sb_info *sbi, struct inode *dir, ++ struct inode *inode, const unsigned char *name) ++{ ++ __u8 (*extlist)[F2FS_EXTENSION_LEN] = sbi->raw_super->extension_list; ++ unsigned char (*noext)[F2FS_EXTENSION_LEN] = ++ F2FS_OPTION(sbi).noextensions; ++ unsigned char (*ext)[F2FS_EXTENSION_LEN] = F2FS_OPTION(sbi).extensions; ++ unsigned char ext_cnt = F2FS_OPTION(sbi).compress_ext_cnt; ++ unsigned char noext_cnt = F2FS_OPTION(sbi).nocompress_ext_cnt; ++ int i, cold_count, hot_count; ++ ++ if (!f2fs_sb_has_compression(sbi)) ++ return; ++ ++ if (S_ISDIR(inode->i_mode)) ++ goto inherit_comp; ++ ++ /* This name comes only from normal files. */ ++ if (!name) ++ return; ++ ++ /* Don't compress hot files. */ ++ f2fs_down_read(&sbi->sb_lock); ++ cold_count = le32_to_cpu(sbi->raw_super->extension_count); ++ hot_count = sbi->raw_super->hot_ext_count; ++ for (i = cold_count; i < cold_count + hot_count; i++) ++ if (is_extension_exist(name, extlist[i], false)) ++ break; ++ f2fs_up_read(&sbi->sb_lock); ++ if (i < (cold_count + hot_count)) ++ return; ++ ++ /* Don't compress unallowed extension. */ ++ for (i = 0; i < noext_cnt; i++) ++ if (is_extension_exist(name, noext[i], false)) ++ return; ++ ++ /* Compress wanting extension. */ ++ for (i = 0; i < ext_cnt; i++) { ++ if (is_extension_exist(name, ext[i], false)) { ++ set_compress_context(inode); ++ return; ++ } ++ } ++inherit_comp: ++ /* Inherit the {no-}compression flag in directory */ ++ if (F2FS_I(dir)->i_flags & F2FS_NOCOMP_FL) { ++ F2FS_I(inode)->i_flags |= F2FS_NOCOMP_FL; ++ f2fs_mark_inode_dirty_sync(inode, true); ++ } else if (F2FS_I(dir)->i_flags & F2FS_COMPR_FL) { ++ set_compress_context(inode); ++ } ++} ++ + static struct inode *f2fs_new_inode(struct user_namespace *mnt_userns, +- struct inode *dir, umode_t mode) ++ struct inode *dir, umode_t mode, ++ const char *name) + { + struct f2fs_sb_info *sbi = F2FS_I_SB(dir); + nid_t ino; +@@ -114,12 +269,8 @@ static struct inode *f2fs_new_inode(struct user_namespace *mnt_userns, + if (F2FS_I(inode)->i_flags & F2FS_PROJINHERIT_FL) + set_inode_flag(inode, FI_PROJ_INHERIT); + +- if (f2fs_sb_has_compression(sbi)) { +- /* Inherit the compression flag in directory */ +- if ((F2FS_I(dir)->i_flags & F2FS_COMPR_FL) && +- f2fs_may_compress(inode)) +- set_compress_context(inode); +- } ++ /* Check compression first. */ ++ set_compress_new_inode(sbi, dir, inode, name); + + /* Should enable inline_data after compression set */ + if (test_opt(sbi, INLINE_DATA) && f2fs_may_inline_data(inode)) +@@ -153,40 +304,6 @@ fail_drop: + return ERR_PTR(err); + } + +-static inline int is_extension_exist(const unsigned char *s, const char *sub, +- bool tmp_ext) +-{ +- size_t slen = strlen(s); +- size_t sublen = strlen(sub); +- int i; +- +- if (sublen == 1 && *sub == '*') +- return 1; +- +- /* +- * filename format of multimedia file should be defined as: +- * "filename + '.' + extension + (optional: '.' + temp extension)". +- */ +- if (slen < sublen + 2) +- return 0; +- +- if (!tmp_ext) { +- /* file has no temp extension */ +- if (s[slen - sublen - 1] != '.') +- return 0; +- return !strncasecmp(s + slen - sublen, sub, sublen); +- } +- +- for (i = 1; i < slen - sublen; i++) { +- if (s[i] != '.') +- continue; +- if (!strncasecmp(s + i + 1, sub, sublen)) +- return 1; +- } +- +- return 0; +-} +- + /* + * Set file's temperature for hot/cold data separation + */ +@@ -217,124 +334,6 @@ static inline void set_file_temperature(struct f2fs_sb_info *sbi, struct inode * + file_set_hot(inode); + } + +-int f2fs_update_extension_list(struct f2fs_sb_info *sbi, const char *name, +- bool hot, bool set) +-{ +- __u8 (*extlist)[F2FS_EXTENSION_LEN] = sbi->raw_super->extension_list; +- int cold_count = le32_to_cpu(sbi->raw_super->extension_count); +- int hot_count = sbi->raw_super->hot_ext_count; +- int total_count = cold_count + hot_count; +- int start, count; +- int i; +- +- if (set) { +- if (total_count == F2FS_MAX_EXTENSION) +- return -EINVAL; +- } else { +- if (!hot && !cold_count) +- return -EINVAL; +- if (hot && !hot_count) +- return -EINVAL; +- } +- +- if (hot) { +- start = cold_count; +- count = total_count; +- } else { +- start = 0; +- count = cold_count; +- } +- +- for (i = start; i < count; i++) { +- if (strcmp(name, extlist[i])) +- continue; +- +- if (set) +- return -EINVAL; +- +- memcpy(extlist[i], extlist[i + 1], +- F2FS_EXTENSION_LEN * (total_count - i - 1)); +- memset(extlist[total_count - 1], 0, F2FS_EXTENSION_LEN); +- if (hot) +- sbi->raw_super->hot_ext_count = hot_count - 1; +- else +- sbi->raw_super->extension_count = +- cpu_to_le32(cold_count - 1); +- return 0; +- } +- +- if (!set) +- return -EINVAL; +- +- if (hot) { +- memcpy(extlist[count], name, strlen(name)); +- sbi->raw_super->hot_ext_count = hot_count + 1; +- } else { +- char buf[F2FS_MAX_EXTENSION][F2FS_EXTENSION_LEN]; +- +- memcpy(buf, &extlist[cold_count], +- F2FS_EXTENSION_LEN * hot_count); +- memset(extlist[cold_count], 0, F2FS_EXTENSION_LEN); +- memcpy(extlist[cold_count], name, strlen(name)); +- memcpy(&extlist[cold_count + 1], buf, +- F2FS_EXTENSION_LEN * hot_count); +- sbi->raw_super->extension_count = cpu_to_le32(cold_count + 1); +- } +- return 0; +-} +- +-static void set_compress_inode(struct f2fs_sb_info *sbi, struct inode *inode, +- const unsigned char *name) +-{ +- __u8 (*extlist)[F2FS_EXTENSION_LEN] = sbi->raw_super->extension_list; +- unsigned char (*noext)[F2FS_EXTENSION_LEN] = F2FS_OPTION(sbi).noextensions; +- unsigned char (*ext)[F2FS_EXTENSION_LEN] = F2FS_OPTION(sbi).extensions; +- unsigned char ext_cnt = F2FS_OPTION(sbi).compress_ext_cnt; +- unsigned char noext_cnt = F2FS_OPTION(sbi).nocompress_ext_cnt; +- int i, cold_count, hot_count; +- +- if (!f2fs_sb_has_compression(sbi) || +- F2FS_I(inode)->i_flags & F2FS_NOCOMP_FL || +- !f2fs_may_compress(inode) || +- (!ext_cnt && !noext_cnt)) +- return; +- +- f2fs_down_read(&sbi->sb_lock); +- +- cold_count = le32_to_cpu(sbi->raw_super->extension_count); +- hot_count = sbi->raw_super->hot_ext_count; +- +- for (i = cold_count; i < cold_count + hot_count; i++) { +- if (is_extension_exist(name, extlist[i], false)) { +- f2fs_up_read(&sbi->sb_lock); +- return; +- } +- } +- +- f2fs_up_read(&sbi->sb_lock); +- +- for (i = 0; i < noext_cnt; i++) { +- if (is_extension_exist(name, noext[i], false)) { +- f2fs_disable_compressed_file(inode); +- return; +- } +- } +- +- if (is_inode_flag_set(inode, FI_COMPRESSED_FILE)) +- return; +- +- for (i = 0; i < ext_cnt; i++) { +- if (!is_extension_exist(name, ext[i], false)) +- continue; +- +- /* Do not use inline_data with compression */ +- stat_dec_inline_inode(inode); +- clear_inode_flag(inode, FI_INLINE_DATA); +- set_compress_context(inode); +- return; +- } +-} +- + static int f2fs_create(struct user_namespace *mnt_userns, struct inode *dir, + struct dentry *dentry, umode_t mode, bool excl) + { +@@ -352,15 +351,13 @@ static int f2fs_create(struct user_namespace *mnt_userns, struct inode *dir, + if (err) + return err; + +- inode = f2fs_new_inode(mnt_userns, dir, mode); ++ inode = f2fs_new_inode(mnt_userns, dir, mode, dentry->d_name.name); + if (IS_ERR(inode)) + return PTR_ERR(inode); + + if (!test_opt(sbi, DISABLE_EXT_IDENTIFY)) + set_file_temperature(sbi, inode, dentry->d_name.name); + +- set_compress_inode(sbi, inode, dentry->d_name.name); +- + inode->i_op = &f2fs_file_inode_operations; + inode->i_fop = &f2fs_file_operations; + inode->i_mapping->a_ops = &f2fs_dblock_aops; +@@ -689,7 +686,7 @@ static int f2fs_symlink(struct user_namespace *mnt_userns, struct inode *dir, + if (err) + return err; + +- inode = f2fs_new_inode(mnt_userns, dir, S_IFLNK | S_IRWXUGO); ++ inode = f2fs_new_inode(mnt_userns, dir, S_IFLNK | S_IRWXUGO, NULL); + if (IS_ERR(inode)) + return PTR_ERR(inode); + +@@ -760,7 +757,7 @@ static int f2fs_mkdir(struct user_namespace *mnt_userns, struct inode *dir, + if (err) + return err; + +- inode = f2fs_new_inode(mnt_userns, dir, S_IFDIR | mode); ++ inode = f2fs_new_inode(mnt_userns, dir, S_IFDIR | mode, NULL); + if (IS_ERR(inode)) + return PTR_ERR(inode); + +@@ -817,7 +814,7 @@ static int f2fs_mknod(struct user_namespace *mnt_userns, struct inode *dir, + if (err) + return err; + +- inode = f2fs_new_inode(mnt_userns, dir, mode); ++ inode = f2fs_new_inode(mnt_userns, dir, mode, NULL); + if (IS_ERR(inode)) + return PTR_ERR(inode); + +@@ -856,7 +853,7 @@ static int __f2fs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir, + if (err) + return err; + +- inode = f2fs_new_inode(mnt_userns, dir, mode); ++ inode = f2fs_new_inode(mnt_userns, dir, mode, NULL); + if (IS_ERR(inode)) + return PTR_ERR(inode); + +diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c +index 983572f238969..b9ee5a1176a07 100644 +--- a/fs/f2fs/node.c ++++ b/fs/f2fs/node.c +@@ -1360,8 +1360,7 @@ static int read_node_page(struct page *page, blk_opf_t op_flags) + return err; + + /* NEW_ADDR can be seen, after cp_error drops some dirty node pages */ +- if (unlikely(ni.blk_addr == NULL_ADDR || ni.blk_addr == NEW_ADDR) || +- is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN)) { ++ if (unlikely(ni.blk_addr == NULL_ADDR || ni.blk_addr == NEW_ADDR)) { + ClearPageUptodate(page); + return -ENOENT; + } +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index acf3d3fa43635..c1d0713666ee5 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -1170,7 +1170,7 @@ submit: + + atomic_inc(&dcc->issued_discard); + +- f2fs_update_iostat(sbi, NULL, FS_DISCARD, 1); ++ f2fs_update_iostat(sbi, NULL, FS_DISCARD, len * F2FS_BLKSIZE); + + lstart += len; + start += len; +@@ -1448,7 +1448,7 @@ retry: + if (i + 1 < dpolicy->granularity) + break; + +- if (i < DEFAULT_DISCARD_GRANULARITY && dpolicy->ordered) ++ if (i + 1 < DEFAULT_DISCARD_GRANULARITY && dpolicy->ordered) + return __issue_discard_cmd_orderly(sbi, dpolicy); + + pend_list = &dcc->pend_list[i]; +@@ -2025,8 +2025,10 @@ int f2fs_start_discard_thread(struct f2fs_sb_info *sbi) + + dcc->f2fs_issue_discard = kthread_run(issue_discard_thread, sbi, + "f2fs_discard-%u:%u", MAJOR(dev), MINOR(dev)); +- if (IS_ERR(dcc->f2fs_issue_discard)) ++ if (IS_ERR(dcc->f2fs_issue_discard)) { + err = PTR_ERR(dcc->f2fs_issue_discard); ++ dcc->f2fs_issue_discard = NULL; ++ } + + return err; + } +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 3834ead046200..67d51f5276061 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -4188,6 +4188,9 @@ try_onemore: + if (err) + goto free_bio_info; + ++ spin_lock_init(&sbi->error_lock); ++ memcpy(sbi->errors, raw_super->s_errors, MAX_F2FS_ERRORS); ++ + init_f2fs_rwsem(&sbi->cp_rwsem); + init_f2fs_rwsem(&sbi->quota_sem); + init_waitqueue_head(&sbi->cp_wait); +@@ -4255,9 +4258,6 @@ try_onemore: + goto free_devices; + } + +- spin_lock_init(&sbi->error_lock); +- memcpy(sbi->errors, raw_super->s_errors, MAX_F2FS_ERRORS); +- + sbi->total_valid_node_count = + le32_to_cpu(sbi->ckpt->valid_node_count); + percpu_counter_set(&sbi->total_valid_inode_count, +@@ -4523,9 +4523,9 @@ free_nm: + f2fs_destroy_node_manager(sbi); + free_sm: + f2fs_destroy_segment_manager(sbi); +- f2fs_destroy_post_read_wq(sbi); + stop_ckpt_thread: + f2fs_stop_ckpt_thread(sbi); ++ f2fs_destroy_post_read_wq(sbi); + free_devices: + destroy_device_list(sbi); + kvfree(sbi->ckpt); +diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c +index df335c258eb08..235a0948f6cc6 100644 +--- a/fs/gfs2/glock.c ++++ b/fs/gfs2/glock.c +@@ -1039,6 +1039,7 @@ static void delete_work_func(struct work_struct *work) + if (gfs2_queue_delete_work(gl, 5 * HZ)) + return; + } ++ goto out; + } + + inode = gfs2_lookup_by_inum(sdp, no_addr, gl->gl_no_formal_ino, +@@ -1051,6 +1052,7 @@ static void delete_work_func(struct work_struct *work) + d_prune_aliases(inode); + iput(inode); + } ++out: + gfs2_glock_put(gl); + } + +diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c +index c4526f16355d5..a0746be3c1de7 100644 +--- a/fs/hfs/inode.c ++++ b/fs/hfs/inode.c +@@ -458,6 +458,8 @@ int hfs_write_inode(struct inode *inode, struct writeback_control *wbc) + /* panic? */ + return -EIO; + ++ if (HFS_I(main_inode)->cat_key.CName.len > HFS_NAMELEN) ++ return -EIO; + fd.search_key->cat = HFS_I(main_inode)->cat_key; + if (hfs_brec_find(&fd)) + /* panic? */ +diff --git a/fs/hfs/trans.c b/fs/hfs/trans.c +index 39f5e343bf4d4..fdb0edb8a607d 100644 +--- a/fs/hfs/trans.c ++++ b/fs/hfs/trans.c +@@ -109,7 +109,7 @@ void hfs_asc2mac(struct super_block *sb, struct hfs_name *out, const struct qstr + if (nls_io) { + wchar_t ch; + +- while (srclen > 0) { ++ while (srclen > 0 && dstlen > 0) { + size = nls_io->char2uni(src, srclen, &ch); + if (size < 0) { + ch = '?'; +diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h +index a5db2e3b29801..6aa919e594834 100644 +--- a/fs/hfsplus/hfsplus_fs.h ++++ b/fs/hfsplus/hfsplus_fs.h +@@ -198,6 +198,8 @@ struct hfsplus_sb_info { + #define HFSPLUS_SB_HFSX 3 + #define HFSPLUS_SB_CASEFOLD 4 + #define HFSPLUS_SB_NOBARRIER 5 ++#define HFSPLUS_SB_UID 6 ++#define HFSPLUS_SB_GID 7 + + static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb) + { +diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c +index aeab83ed1c9c6..b675581aa9d0f 100644 +--- a/fs/hfsplus/inode.c ++++ b/fs/hfsplus/inode.c +@@ -192,11 +192,11 @@ static void hfsplus_get_perms(struct inode *inode, + mode = be16_to_cpu(perms->mode); + + i_uid_write(inode, be32_to_cpu(perms->owner)); +- if (!i_uid_read(inode) && !mode) ++ if ((test_bit(HFSPLUS_SB_UID, &sbi->flags)) || (!i_uid_read(inode) && !mode)) + inode->i_uid = sbi->uid; + + i_gid_write(inode, be32_to_cpu(perms->group)); +- if (!i_gid_read(inode) && !mode) ++ if ((test_bit(HFSPLUS_SB_GID, &sbi->flags)) || (!i_gid_read(inode) && !mode)) + inode->i_gid = sbi->gid; + + if (dir) { +diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c +index 047e05c575601..c94a58762ad6d 100644 +--- a/fs/hfsplus/options.c ++++ b/fs/hfsplus/options.c +@@ -140,6 +140,8 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi) + if (!uid_valid(sbi->uid)) { + pr_err("invalid uid specified\n"); + return 0; ++ } else { ++ set_bit(HFSPLUS_SB_UID, &sbi->flags); + } + break; + case opt_gid: +@@ -151,6 +153,8 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi) + if (!gid_valid(sbi->gid)) { + pr_err("invalid gid specified\n"); + return 0; ++ } else { ++ set_bit(HFSPLUS_SB_GID, &sbi->flags); + } + break; + case opt_part: +diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c +index df7772335dc0e..8eea709e36599 100644 +--- a/fs/hugetlbfs/inode.c ++++ b/fs/hugetlbfs/inode.c +@@ -1377,7 +1377,7 @@ static int hugetlbfs_parse_param(struct fs_context *fc, struct fs_parameter *par + + case Opt_size: + /* memparse() will accept a K/M/G without a digit */ +- if (!isdigit(param->string[0])) ++ if (!param->string || !isdigit(param->string[0])) + goto bad_val; + ctx->max_size_opt = memparse(param->string, &rest); + ctx->max_val_type = SIZE_STD; +@@ -1387,7 +1387,7 @@ static int hugetlbfs_parse_param(struct fs_context *fc, struct fs_parameter *par + + case Opt_nr_inodes: + /* memparse() will accept a K/M/G without a digit */ +- if (!isdigit(param->string[0])) ++ if (!param->string || !isdigit(param->string[0])) + goto bad_val; + ctx->nr_inodes = memparse(param->string, &rest); + return 0; +@@ -1403,7 +1403,7 @@ static int hugetlbfs_parse_param(struct fs_context *fc, struct fs_parameter *par + + case Opt_min_size: + /* memparse() will accept a K/M/G without a digit */ +- if (!isdigit(param->string[0])) ++ if (!param->string || !isdigit(param->string[0])) + goto bad_val; + ctx->min_size_opt = memparse(param->string, &rest); + ctx->min_val_type = SIZE_STD; +diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c +index 6b838d3ae7c2e..765838578a722 100644 +--- a/fs/jfs/jfs_dmap.c ++++ b/fs/jfs/jfs_dmap.c +@@ -155,7 +155,7 @@ int dbMount(struct inode *ipbmap) + struct bmap *bmp; + struct dbmap_disk *dbmp_le; + struct metapage *mp; +- int i; ++ int i, err; + + /* + * allocate/initialize the in-memory bmap descriptor +@@ -170,8 +170,8 @@ int dbMount(struct inode *ipbmap) + BMAPBLKNO << JFS_SBI(ipbmap->i_sb)->l2nbperpage, + PSIZE, 0); + if (mp == NULL) { +- kfree(bmp); +- return -EIO; ++ err = -EIO; ++ goto err_kfree_bmp; + } + + /* copy the on-disk bmap descriptor to its in-memory version. */ +@@ -181,9 +181,8 @@ int dbMount(struct inode *ipbmap) + bmp->db_l2nbperpage = le32_to_cpu(dbmp_le->dn_l2nbperpage); + bmp->db_numag = le32_to_cpu(dbmp_le->dn_numag); + if (!bmp->db_numag) { +- release_metapage(mp); +- kfree(bmp); +- return -EINVAL; ++ err = -EINVAL; ++ goto err_release_metapage; + } + + bmp->db_maxlevel = le32_to_cpu(dbmp_le->dn_maxlevel); +@@ -194,6 +193,16 @@ int dbMount(struct inode *ipbmap) + bmp->db_agwidth = le32_to_cpu(dbmp_le->dn_agwidth); + bmp->db_agstart = le32_to_cpu(dbmp_le->dn_agstart); + bmp->db_agl2size = le32_to_cpu(dbmp_le->dn_agl2size); ++ if (bmp->db_agl2size > L2MAXL2SIZE - L2MAXAG) { ++ err = -EINVAL; ++ goto err_release_metapage; ++ } ++ ++ if (((bmp->db_mapsize - 1) >> bmp->db_agl2size) > MAXAG) { ++ err = -EINVAL; ++ goto err_release_metapage; ++ } ++ + for (i = 0; i < MAXAG; i++) + bmp->db_agfree[i] = le64_to_cpu(dbmp_le->dn_agfree[i]); + bmp->db_agsize = le64_to_cpu(dbmp_le->dn_agsize); +@@ -214,6 +223,12 @@ int dbMount(struct inode *ipbmap) + BMAP_LOCK_INIT(bmp); + + return (0); ++ ++err_release_metapage: ++ release_metapage(mp); ++err_kfree_bmp: ++ kfree(bmp); ++ return err; + } + + +diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c +index 9db4f5789c0ec..4fbbf88435e69 100644 +--- a/fs/jfs/namei.c ++++ b/fs/jfs/namei.c +@@ -946,7 +946,7 @@ static int jfs_symlink(struct user_namespace *mnt_userns, struct inode *dip, + if (ssize <= IDATASIZE) { + ip->i_op = &jfs_fast_symlink_inode_operations; + +- ip->i_link = JFS_IP(ip)->i_inline; ++ ip->i_link = JFS_IP(ip)->i_inline_all; + memcpy(ip->i_link, name, ssize); + ip->i_size = ssize - 1; + +diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c +index 3fa2139a0b309..92b1603b5abeb 100644 +--- a/fs/ksmbd/mgmt/user_session.c ++++ b/fs/ksmbd/mgmt/user_session.c +@@ -108,15 +108,17 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name) + entry->method = method; + entry->id = ksmbd_ipc_id_alloc(); + if (entry->id < 0) +- goto error; ++ goto free_entry; + + resp = ksmbd_rpc_open(sess, entry->id); + if (!resp) +- goto error; ++ goto free_id; + + kvfree(resp); + return entry->id; +-error: ++free_id: ++ ksmbd_rpc_id_free(entry->id); ++free_entry: + list_del(&entry->list); + kfree(entry); + return -EINVAL; +diff --git a/fs/libfs.c b/fs/libfs.c +index 682d56345a1cf..aada4e7c87132 100644 +--- a/fs/libfs.c ++++ b/fs/libfs.c +@@ -995,8 +995,8 @@ out: + EXPORT_SYMBOL_GPL(simple_attr_read); + + /* interpret the buffer as a number to call the set function with */ +-ssize_t simple_attr_write(struct file *file, const char __user *buf, +- size_t len, loff_t *ppos) ++static ssize_t simple_attr_write_xsigned(struct file *file, const char __user *buf, ++ size_t len, loff_t *ppos, bool is_signed) + { + struct simple_attr *attr; + unsigned long long val; +@@ -1017,7 +1017,10 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf, + goto out; + + attr->set_buf[size] = '\0'; +- ret = kstrtoull(attr->set_buf, 0, &val); ++ if (is_signed) ++ ret = kstrtoll(attr->set_buf, 0, &val); ++ else ++ ret = kstrtoull(attr->set_buf, 0, &val); + if (ret) + goto out; + ret = attr->set(attr->data, val); +@@ -1027,8 +1030,21 @@ out: + mutex_unlock(&attr->mutex); + return ret; + } ++ ++ssize_t simple_attr_write(struct file *file, const char __user *buf, ++ size_t len, loff_t *ppos) ++{ ++ return simple_attr_write_xsigned(file, buf, len, ppos, false); ++} + EXPORT_SYMBOL_GPL(simple_attr_write); + ++ssize_t simple_attr_write_signed(struct file *file, const char __user *buf, ++ size_t len, loff_t *ppos) ++{ ++ return simple_attr_write_xsigned(file, buf, len, ppos, true); ++} ++EXPORT_SYMBOL_GPL(simple_attr_write_signed); ++ + /** + * generic_fh_to_dentry - generic helper for the fh_to_dentry export operation + * @sb: filesystem to do the file handle conversion on +diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c +index e1c4617de7714..3515f17eaf3fb 100644 +--- a/fs/lockd/svcsubs.c ++++ b/fs/lockd/svcsubs.c +@@ -176,7 +176,7 @@ nlm_delete_file(struct nlm_file *file) + } + } + +-static int nlm_unlock_files(struct nlm_file *file, fl_owner_t owner) ++static int nlm_unlock_files(struct nlm_file *file, const struct file_lock *fl) + { + struct file_lock lock; + +@@ -184,12 +184,15 @@ static int nlm_unlock_files(struct nlm_file *file, fl_owner_t owner) + lock.fl_type = F_UNLCK; + lock.fl_start = 0; + lock.fl_end = OFFSET_MAX; +- lock.fl_owner = owner; +- if (file->f_file[O_RDONLY] && +- vfs_lock_file(file->f_file[O_RDONLY], F_SETLK, &lock, NULL)) ++ lock.fl_owner = fl->fl_owner; ++ lock.fl_pid = fl->fl_pid; ++ lock.fl_flags = FL_POSIX; ++ ++ lock.fl_file = file->f_file[O_RDONLY]; ++ if (lock.fl_file && vfs_lock_file(lock.fl_file, 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)) ++ lock.fl_file = file->f_file[O_WRONLY]; ++ if (lock.fl_file && vfs_lock_file(lock.fl_file, F_SETLK, &lock, NULL)) + goto out_err; + return 0; + out_err: +@@ -226,7 +229,7 @@ again: + if (match(lockhost, host)) { + + spin_unlock(&flctx->flc_lock); +- if (nlm_unlock_files(file, fl->fl_owner)) ++ if (nlm_unlock_files(file, fl)) + return 1; + goto again; + } +diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c +index 09833ec102fca..9bcd53d5c7d46 100644 +--- a/fs/nfs/fs_context.c ++++ b/fs/nfs/fs_context.c +@@ -684,6 +684,8 @@ static int nfs_fs_context_parse_param(struct fs_context *fc, + return ret; + break; + case Opt_vers: ++ if (!param->string) ++ goto out_invalid_value; + trace_nfs_mount_assign(param->key, param->string); + ret = nfs_parse_version_string(fc, param->string); + if (ret < 0) +@@ -696,6 +698,8 @@ static int nfs_fs_context_parse_param(struct fs_context *fc, + break; + + case Opt_proto: ++ if (!param->string) ++ goto out_invalid_value; + trace_nfs_mount_assign(param->key, param->string); + protofamily = AF_INET; + switch (lookup_constant(nfs_xprt_protocol_tokens, param->string, -1)) { +@@ -732,6 +736,8 @@ static int nfs_fs_context_parse_param(struct fs_context *fc, + break; + + case Opt_mountproto: ++ if (!param->string) ++ goto out_invalid_value; + trace_nfs_mount_assign(param->key, param->string); + mountfamily = AF_INET; + switch (lookup_constant(nfs_xprt_protocol_tokens, param->string, -1)) { +diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h +index 647fc3f547cbe..ae7d4a8c728c2 100644 +--- a/fs/nfs/internal.h ++++ b/fs/nfs/internal.h +@@ -739,12 +739,10 @@ unsigned long nfs_io_size(unsigned long iosize, enum xprt_transports proto) + iosize = NFS_DEF_FILE_IO_SIZE; + else if (iosize >= NFS_MAX_FILE_IO_SIZE) + iosize = NFS_MAX_FILE_IO_SIZE; +- else +- iosize = iosize & PAGE_MASK; + +- if (proto == XPRT_TRANSPORT_UDP) ++ if (proto == XPRT_TRANSPORT_UDP || iosize < PAGE_SIZE) + return nfs_block_bits(iosize, NULL); +- return iosize; ++ return iosize & PAGE_MASK; + } + + /* +diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c +index 2f336ace75554..88a23af2bd5c9 100644 +--- a/fs/nfs/namespace.c ++++ b/fs/nfs/namespace.c +@@ -147,7 +147,7 @@ struct vfsmount *nfs_d_automount(struct path *path) + struct nfs_fs_context *ctx; + struct fs_context *fc; + struct vfsmount *mnt = ERR_PTR(-ENOMEM); +- struct nfs_server *server = NFS_SERVER(d_inode(path->dentry)); ++ struct nfs_server *server = NFS_SB(path->dentry->d_sb); + struct nfs_client *client = server->nfs_client; + int timeout = READ_ONCE(nfs_mountpoint_expiry_timeout); + int ret; +diff --git a/fs/nfs/nfs42xdr.c b/fs/nfs/nfs42xdr.c +index fe1aeb0f048f2..2fd465cab631d 100644 +--- a/fs/nfs/nfs42xdr.c ++++ b/fs/nfs/nfs42xdr.c +@@ -1142,7 +1142,7 @@ static int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res) + if (!segs) + return -ENOMEM; + +- xdr_set_scratch_buffer(xdr, &scratch_buf, 32); ++ xdr_set_scratch_buffer(xdr, &scratch_buf, sizeof(scratch_buf)); + status = -EIO; + for (i = 0; i < segments; i++) { + status = decode_read_plus_segment(xdr, &segs[i]); +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index 86ed5c0142c3d..e51044a5f550f 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -122,6 +122,11 @@ nfs4_label_init_security(struct inode *dir, struct dentry *dentry, + if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL) == 0) + return NULL; + ++ label->lfs = 0; ++ label->pi = 0; ++ label->len = 0; ++ label->label = NULL; ++ + err = security_dentry_init_security(dentry, sattr->ia_mode, + &dentry->d_name, NULL, + (void **)&label->label, &label->len); +@@ -2126,18 +2131,18 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context + } + + static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, +- fmode_t fmode) ++ fmode_t fmode) + { + struct nfs4_state *newstate; ++ struct nfs_server *server = NFS_SB(opendata->dentry->d_sb); ++ int openflags = opendata->o_arg.open_flags; + int ret; + + if (!nfs4_mode_match_open_stateid(opendata->state, fmode)) + return 0; +- opendata->o_arg.open_flags = 0; + opendata->o_arg.fmode = fmode; +- opendata->o_arg.share_access = nfs4_map_atomic_open_share( +- NFS_SB(opendata->dentry->d_sb), +- fmode, 0); ++ opendata->o_arg.share_access = ++ nfs4_map_atomic_open_share(server, fmode, openflags); + memset(&opendata->o_res, 0, sizeof(opendata->o_res)); + memset(&opendata->c_res, 0, sizeof(opendata->c_res)); + nfs4_init_opendata_res(opendata); +@@ -2719,10 +2724,15 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s + struct nfs4_opendata *opendata; + int ret; + +- opendata = nfs4_open_recoverdata_alloc(ctx, state, +- NFS4_OPEN_CLAIM_FH); ++ opendata = nfs4_open_recoverdata_alloc(ctx, state, NFS4_OPEN_CLAIM_FH); + if (IS_ERR(opendata)) + return PTR_ERR(opendata); ++ /* ++ * We're not recovering a delegation, so ask for no delegation. ++ * Otherwise the recovery thread could deadlock with an outstanding ++ * delegation return. ++ */ ++ opendata->o_arg.open_flags = O_DIRECT; + ret = nfs4_open_recover(opendata, state); + if (ret == -ESTALE) + d_drop(ctx->dentry); +@@ -3796,7 +3806,7 @@ nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, + int open_flags, struct iattr *attr, int *opened) + { + struct nfs4_state *state; +- struct nfs4_label l = {0, 0, 0, NULL}, *label = NULL; ++ struct nfs4_label l, *label; + + label = nfs4_label_init_security(dir, ctx->dentry, attr, &l); + +@@ -4013,7 +4023,7 @@ static int _nfs4_discover_trunking(struct nfs_server *server, + + page = alloc_page(GFP_KERNEL); + if (!page) +- return -ENOMEM; ++ goto out_put_cred; + locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL); + if (!locations) + goto out_free; +@@ -4035,6 +4045,8 @@ out_free_2: + kfree(locations); + out_free: + __free_page(page); ++out_put_cred: ++ put_cred(cred); + return status; + } + +@@ -4682,7 +4694,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, + int flags) + { + struct nfs_server *server = NFS_SERVER(dir); +- struct nfs4_label l, *ilabel = NULL; ++ struct nfs4_label l, *ilabel; + struct nfs_open_context *ctx; + struct nfs4_state *state; + int status = 0; +@@ -5033,7 +5045,7 @@ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, + struct nfs4_exception exception = { + .interruptible = true, + }; +- struct nfs4_label l, *label = NULL; ++ struct nfs4_label l, *label; + int err; + + label = nfs4_label_init_security(dir, dentry, sattr, &l); +@@ -5074,7 +5086,7 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, + struct nfs4_exception exception = { + .interruptible = true, + }; +- struct nfs4_label l, *label = NULL; ++ struct nfs4_label l, *label; + int err; + + label = nfs4_label_init_security(dir, dentry, sattr, &l); +@@ -5193,7 +5205,7 @@ static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, + struct nfs4_exception exception = { + .interruptible = true, + }; +- struct nfs4_label l, *label = NULL; ++ struct nfs4_label l, *label; + int err; + + label = nfs4_label_init_security(dir, dentry, sattr, &l); +diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c +index a2d2d5d1b0888..03087ef1c7b4a 100644 +--- a/fs/nfs/nfs4state.c ++++ b/fs/nfs/nfs4state.c +@@ -1230,6 +1230,8 @@ void nfs4_schedule_state_manager(struct nfs_client *clp) + if (IS_ERR(task)) { + printk(KERN_ERR "%s: kthread_run: %ld\n", + __func__, PTR_ERR(task)); ++ if (!nfs_client_init_is_complete(clp)) ++ nfs_mark_client_ready(clp, PTR_ERR(task)); + nfs4_clear_state_manager_bit(clp); + clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state); + nfs_put_client(clp); +diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c +index acfe5f4bda480..deec76cf5afea 100644 +--- a/fs/nfs/nfs4xdr.c ++++ b/fs/nfs/nfs4xdr.c +@@ -4234,19 +4234,17 @@ static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, + p = xdr_inline_decode(xdr, len); + if (unlikely(!p)) + return -EIO; ++ bitmap[2] &= ~FATTR4_WORD2_SECURITY_LABEL; + if (len < NFS4_MAXLABELLEN) { +- if (label) { +- if (label->len) { +- if (label->len < len) +- return -ERANGE; +- memcpy(label->label, p, len); +- } ++ if (label && label->len) { ++ if (label->len < len) ++ return -ERANGE; ++ memcpy(label->label, p, len); + label->len = len; + label->pi = pi; + label->lfs = lfs; + status = NFS_ATTR_FATTR_V4_SECURITY_LABEL; + } +- bitmap[2] &= ~FATTR4_WORD2_SECURITY_LABEL; + } else + printk(KERN_WARNING "%s: label too long (%u)!\n", + __func__, len); +@@ -4755,12 +4753,10 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, + if (status < 0) + goto xdr_error; + +- if (fattr->label) { +- status = decode_attr_security_label(xdr, bitmap, fattr->label); +- if (status < 0) +- goto xdr_error; +- fattr->valid |= status; +- } ++ status = decode_attr_security_label(xdr, bitmap, fattr->label); ++ if (status < 0) ++ goto xdr_error; ++ fattr->valid |= status; + + xdr_error: + dprintk("%s: xdr returned %d\n", __func__, -status); +diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c +index 13e6e6897f6cf..65d4511b7af08 100644 +--- a/fs/nfsd/nfs2acl.c ++++ b/fs/nfsd/nfs2acl.c +@@ -246,7 +246,6 @@ nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, struct xdr_stream *xdr) + struct nfsd3_getaclres *resp = rqstp->rq_resp; + struct dentry *dentry = resp->fh.fh_dentry; + struct inode *inode; +- int w; + + if (!svcxdr_encode_stat(xdr, resp->status)) + return false; +@@ -260,15 +259,6 @@ nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, struct xdr_stream *xdr) + if (xdr_stream_encode_u32(xdr, resp->mask) < 0) + return false; + +- rqstp->rq_res.page_len = w = nfsacl_size( +- (resp->mask & NFS_ACL) ? resp->acl_access : NULL, +- (resp->mask & NFS_DFACL) ? resp->acl_default : NULL); +- while (w > 0) { +- if (!*(rqstp->rq_next_page++)) +- return true; +- w -= PAGE_SIZE; +- } +- + if (!nfs_stream_encode_acl(xdr, inode, resp->acl_access, + resp->mask & NFS_ACL, 0)) + return false; +diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c +index 2fb9ee3564558..a34a22e272ad5 100644 +--- a/fs/nfsd/nfs3acl.c ++++ b/fs/nfsd/nfs3acl.c +@@ -171,11 +171,7 @@ nfs3svc_encode_getaclres(struct svc_rqst *rqstp, struct xdr_stream *xdr) + { + struct nfsd3_getaclres *resp = rqstp->rq_resp; + struct dentry *dentry = resp->fh.fh_dentry; +- struct kvec *head = rqstp->rq_res.head; + struct inode *inode; +- unsigned int base; +- int n; +- int w; + + if (!svcxdr_encode_nfsstat3(xdr, resp->status)) + return false; +@@ -187,26 +183,12 @@ nfs3svc_encode_getaclres(struct svc_rqst *rqstp, struct xdr_stream *xdr) + if (xdr_stream_encode_u32(xdr, resp->mask) < 0) + return false; + +- base = (char *)xdr->p - (char *)head->iov_base; +- +- rqstp->rq_res.page_len = w = nfsacl_size( +- (resp->mask & NFS_ACL) ? resp->acl_access : NULL, +- (resp->mask & NFS_DFACL) ? resp->acl_default : NULL); +- while (w > 0) { +- if (!*(rqstp->rq_next_page++)) +- return false; +- w -= PAGE_SIZE; +- } +- +- n = nfsacl_encode(&rqstp->rq_res, base, inode, +- resp->acl_access, +- resp->mask & NFS_ACL, 0); +- if (n > 0) +- n = nfsacl_encode(&rqstp->rq_res, base + n, inode, +- resp->acl_default, +- resp->mask & NFS_DFACL, +- NFS_ACL_DEFAULT); +- if (n <= 0) ++ if (!nfs_stream_encode_acl(xdr, inode, resp->acl_access, ++ resp->mask & NFS_ACL, 0)) ++ return false; ++ if (!nfs_stream_encode_acl(xdr, inode, resp->acl_default, ++ resp->mask & NFS_DFACL, ++ NFS_ACL_DEFAULT)) + return false; + break; + default: +diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c +index f0e69edf5f0f1..6253cbe5f81b4 100644 +--- a/fs/nfsd/nfs4callback.c ++++ b/fs/nfsd/nfs4callback.c +@@ -916,7 +916,6 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c + } else { + if (!conn->cb_xprt) + return -EINVAL; +- clp->cl_cb_conn.cb_xprt = conn->cb_xprt; + clp->cl_cb_session = ses; + args.bc_xprt = conn->cb_xprt; + args.prognumber = clp->cl_cb_session->se_cb_prog; +@@ -936,6 +935,9 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c + rpc_shutdown_client(client); + return -ENOMEM; + } ++ ++ if (clp->cl_minorversion != 0) ++ clp->cl_cb_conn.cb_xprt = conn->cb_xprt; + clp->cl_cb_client = client; + clp->cl_cb_cred = cred; + rcu_read_lock(); +diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c +index 8beb2bc4c328f..34d1cd5883fbb 100644 +--- a/fs/nfsd/nfs4proc.c ++++ b/fs/nfsd/nfs4proc.c +@@ -1133,6 +1133,8 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, + 0, (time64_t)0); + if (!status) + status = nfserrno(attrs.na_labelerr); ++ if (!status) ++ status = nfserrno(attrs.na_aclerr); + out: + nfsd_attrs_free(&attrs); + fh_drop_write(&cstate->current_fh); +@@ -1463,13 +1465,6 @@ out_err: + return status; + } + +-static void +-nfsd4_interssc_disconnect(struct vfsmount *ss_mnt) +-{ +- nfs_do_sb_deactive(ss_mnt->mnt_sb); +- mntput(ss_mnt); +-} +- + /* + * Verify COPY destination stateid. + * +@@ -1572,11 +1567,6 @@ nfsd4_cleanup_inter_ssc(struct vfsmount *ss_mnt, struct file *filp, + { + } + +-static void +-nfsd4_interssc_disconnect(struct vfsmount *ss_mnt) +-{ +-} +- + static struct file *nfs42_ssc_open(struct vfsmount *ss_mnt, + struct nfs_fh *src_fh, + nfs4_stateid *stateid) +@@ -1644,6 +1634,7 @@ static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy, + u64 src_pos = copy->cp_src_pos; + u64 dst_pos = copy->cp_dst_pos; + int status; ++ loff_t end; + + /* See RFC 7862 p.67: */ + if (bytes_total == 0) +@@ -1663,8 +1654,8 @@ static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy, + /* for a non-zero asynchronous copy do a commit of data */ + if (nfsd4_copy_is_async(copy) && copy->cp_res.wr_bytes_written > 0) { + since = READ_ONCE(dst->f_wb_err); +- status = vfs_fsync_range(dst, copy->cp_dst_pos, +- copy->cp_res.wr_bytes_written, 0); ++ end = copy->cp_dst_pos + copy->cp_res.wr_bytes_written - 1; ++ status = vfs_fsync_range(dst, copy->cp_dst_pos, end, 0); + if (!status) + status = filemap_check_wb_err(dst->f_mapping, since); + if (!status) +@@ -1771,7 +1762,7 @@ static int nfsd4_do_async_copy(void *data) + default: + nfserr = nfserr_offload_denied; + } +- nfsd4_interssc_disconnect(copy->ss_mnt); ++ /* ss_mnt will be unmounted by the laundromat */ + goto do_callback; + } + nfserr = nfsd4_do_copy(copy, filp, copy->nf_dst->nf_file, +@@ -1852,8 +1843,10 @@ out_err: + if (async_copy) + cleanup_async_copy(async_copy); + status = nfserrno(-ENOMEM); +- if (nfsd4_ssc_is_inter(copy)) +- nfsd4_interssc_disconnect(copy->ss_mnt); ++ /* ++ * source's vfsmount of inter-copy will be unmounted ++ * by the laundromat ++ */ + goto out; + } + +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index 836bd825ca4ad..52b5552d0d70e 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -675,15 +675,26 @@ find_any_file(struct nfs4_file *f) + return ret; + } + +-static struct nfsd_file *find_deleg_file(struct nfs4_file *f) ++static struct nfsd_file *find_any_file_locked(struct nfs4_file *f) + { +- struct nfsd_file *ret = NULL; ++ lockdep_assert_held(&f->fi_lock); ++ ++ if (f->fi_fds[O_RDWR]) ++ return f->fi_fds[O_RDWR]; ++ if (f->fi_fds[O_WRONLY]) ++ return f->fi_fds[O_WRONLY]; ++ if (f->fi_fds[O_RDONLY]) ++ return f->fi_fds[O_RDONLY]; ++ return NULL; ++} ++ ++static struct nfsd_file *find_deleg_file_locked(struct nfs4_file *f) ++{ ++ lockdep_assert_held(&f->fi_lock); + +- spin_lock(&f->fi_lock); + if (f->fi_deleg_file) +- ret = nfsd_file_get(f->fi_deleg_file); +- spin_unlock(&f->fi_lock); +- return ret; ++ return f->fi_deleg_file; ++ return NULL; + } + + static atomic_long_t num_delegations; +@@ -2613,9 +2624,11 @@ static int nfs4_show_open(struct seq_file *s, struct nfs4_stid *st) + ols = openlockstateid(st); + oo = ols->st_stateowner; + nf = st->sc_file; +- file = find_any_file(nf); ++ ++ spin_lock(&nf->fi_lock); ++ file = find_any_file_locked(nf); + if (!file) +- return 0; ++ goto out; + + seq_printf(s, "- "); + nfs4_show_stateid(s, &st->sc_stateid); +@@ -2637,8 +2650,8 @@ static int nfs4_show_open(struct seq_file *s, struct nfs4_stid *st) + seq_printf(s, ", "); + nfs4_show_owner(s, oo); + seq_printf(s, " }\n"); +- nfsd_file_put(file); +- ++out: ++ spin_unlock(&nf->fi_lock); + return 0; + } + +@@ -2652,9 +2665,10 @@ static int nfs4_show_lock(struct seq_file *s, struct nfs4_stid *st) + ols = openlockstateid(st); + oo = ols->st_stateowner; + nf = st->sc_file; +- file = find_any_file(nf); ++ spin_lock(&nf->fi_lock); ++ file = find_any_file_locked(nf); + if (!file) +- return 0; ++ goto out; + + seq_printf(s, "- "); + nfs4_show_stateid(s, &st->sc_stateid); +@@ -2674,8 +2688,8 @@ static int nfs4_show_lock(struct seq_file *s, struct nfs4_stid *st) + seq_printf(s, ", "); + nfs4_show_owner(s, oo); + seq_printf(s, " }\n"); +- nfsd_file_put(file); +- ++out: ++ spin_unlock(&nf->fi_lock); + return 0; + } + +@@ -2687,9 +2701,10 @@ static int nfs4_show_deleg(struct seq_file *s, struct nfs4_stid *st) + + ds = delegstateid(st); + nf = st->sc_file; +- file = find_deleg_file(nf); ++ spin_lock(&nf->fi_lock); ++ file = find_deleg_file_locked(nf); + if (!file) +- return 0; ++ goto out; + + seq_printf(s, "- "); + nfs4_show_stateid(s, &st->sc_stateid); +@@ -2705,8 +2720,8 @@ static int nfs4_show_deleg(struct seq_file *s, struct nfs4_stid *st) + seq_printf(s, ", "); + nfs4_show_fname(s, file); + seq_printf(s, " }\n"); +- nfsd_file_put(file); +- ++out: ++ spin_unlock(&nf->fi_lock); + return 0; + } + +diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c +index c8b89b4f94e0e..2064e6473d304 100644 +--- a/fs/nilfs2/the_nilfs.c ++++ b/fs/nilfs2/the_nilfs.c +@@ -13,6 +13,7 @@ + #include <linux/blkdev.h> + #include <linux/backing-dev.h> + #include <linux/random.h> ++#include <linux/log2.h> + #include <linux/crc32.h> + #include "nilfs.h" + #include "segment.h" +@@ -192,6 +193,34 @@ static int nilfs_store_log_cursor(struct the_nilfs *nilfs, + return ret; + } + ++/** ++ * nilfs_get_blocksize - get block size from raw superblock data ++ * @sb: super block instance ++ * @sbp: superblock raw data buffer ++ * @blocksize: place to store block size ++ * ++ * nilfs_get_blocksize() calculates the block size from the block size ++ * exponent information written in @sbp and stores it in @blocksize, ++ * or aborts with an error message if it's too large. ++ * ++ * Return Value: On success, 0 is returned. If the block size is too ++ * large, -EINVAL is returned. ++ */ ++static int nilfs_get_blocksize(struct super_block *sb, ++ struct nilfs_super_block *sbp, int *blocksize) ++{ ++ unsigned int shift_bits = le32_to_cpu(sbp->s_log_block_size); ++ ++ if (unlikely(shift_bits > ++ ilog2(NILFS_MAX_BLOCK_SIZE) - BLOCK_SIZE_BITS)) { ++ nilfs_err(sb, "too large filesystem blocksize: 2 ^ %u KiB", ++ shift_bits); ++ return -EINVAL; ++ } ++ *blocksize = BLOCK_SIZE << shift_bits; ++ return 0; ++} ++ + /** + * load_nilfs - load and recover the nilfs + * @nilfs: the_nilfs structure to be released +@@ -245,11 +274,15 @@ int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb) + nilfs->ns_sbwtime = le64_to_cpu(sbp[0]->s_wtime); + + /* verify consistency between two super blocks */ +- blocksize = BLOCK_SIZE << le32_to_cpu(sbp[0]->s_log_block_size); ++ err = nilfs_get_blocksize(sb, sbp[0], &blocksize); ++ if (err) ++ goto scan_error; ++ + if (blocksize != nilfs->ns_blocksize) { + nilfs_warn(sb, + "blocksize differs between two super blocks (%d != %d)", + blocksize, nilfs->ns_blocksize); ++ err = -EINVAL; + goto scan_error; + } + +@@ -443,11 +476,33 @@ static int nilfs_valid_sb(struct nilfs_super_block *sbp) + return crc == le32_to_cpu(sbp->s_sum); + } + +-static int nilfs_sb2_bad_offset(struct nilfs_super_block *sbp, u64 offset) ++/** ++ * nilfs_sb2_bad_offset - check the location of the second superblock ++ * @sbp: superblock raw data buffer ++ * @offset: byte offset of second superblock calculated from device size ++ * ++ * nilfs_sb2_bad_offset() checks if the position on the second ++ * superblock is valid or not based on the filesystem parameters ++ * stored in @sbp. If @offset points to a location within the segment ++ * area, or if the parameters themselves are not normal, it is ++ * determined to be invalid. ++ * ++ * Return Value: true if invalid, false if valid. ++ */ ++static bool nilfs_sb2_bad_offset(struct nilfs_super_block *sbp, u64 offset) + { +- return offset < ((le64_to_cpu(sbp->s_nsegments) * +- le32_to_cpu(sbp->s_blocks_per_segment)) << +- (le32_to_cpu(sbp->s_log_block_size) + 10)); ++ unsigned int shift_bits = le32_to_cpu(sbp->s_log_block_size); ++ u32 blocks_per_segment = le32_to_cpu(sbp->s_blocks_per_segment); ++ u64 nsegments = le64_to_cpu(sbp->s_nsegments); ++ u64 index; ++ ++ if (blocks_per_segment < NILFS_SEG_MIN_BLOCKS || ++ shift_bits > ilog2(NILFS_MAX_BLOCK_SIZE) - BLOCK_SIZE_BITS) ++ return true; ++ ++ index = offset >> (shift_bits + BLOCK_SIZE_BITS); ++ do_div(index, blocks_per_segment); ++ return index < nsegments; + } + + static void nilfs_release_super_block(struct the_nilfs *nilfs) +@@ -586,9 +641,11 @@ int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data) + if (err) + goto failed_sbh; + +- blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); +- if (blocksize < NILFS_MIN_BLOCK_SIZE || +- blocksize > NILFS_MAX_BLOCK_SIZE) { ++ err = nilfs_get_blocksize(sb, sbp, &blocksize); ++ if (err) ++ goto failed_sbh; ++ ++ if (blocksize < NILFS_MIN_BLOCK_SIZE) { + nilfs_err(sb, + "couldn't mount because of unsupported filesystem blocksize %d", + blocksize); +diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c +index 71f870d497aed..578c2bcfb1d93 100644 +--- a/fs/ntfs3/attrib.c ++++ b/fs/ntfs3/attrib.c +@@ -101,6 +101,10 @@ static int attr_load_runs(struct ATTRIB *attr, struct ntfs_inode *ni, + + asize = le32_to_cpu(attr->size); + run_off = le16_to_cpu(attr->nres.run_off); ++ ++ if (run_off > asize) ++ return -EINVAL; ++ + err = run_unpack_ex(run, ni->mi.sbi, ni->mi.rno, svcn, evcn, + vcn ? *vcn : svcn, Add2Ptr(attr, run_off), + asize - run_off); +@@ -1217,6 +1221,11 @@ int attr_load_runs_vcn(struct ntfs_inode *ni, enum ATTR_TYPE type, + CLST svcn, evcn; + u16 ro; + ++ if (!ni) { ++ /* Is record corrupted? */ ++ return -ENOENT; ++ } ++ + attr = ni_find_attr(ni, NULL, NULL, type, name, name_len, &vcn, NULL); + if (!attr) { + /* Is record corrupted? */ +@@ -1232,6 +1241,10 @@ int attr_load_runs_vcn(struct ntfs_inode *ni, enum ATTR_TYPE type, + } + + ro = le16_to_cpu(attr->nres.run_off); ++ ++ if (ro > le32_to_cpu(attr->size)) ++ return -EINVAL; ++ + err = run_unpack_ex(run, ni->mi.sbi, ni->mi.rno, svcn, evcn, svcn, + Add2Ptr(attr, ro), le32_to_cpu(attr->size) - ro); + if (err < 0) +@@ -1901,6 +1914,11 @@ int attr_collapse_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) + u16 le_sz; + u16 roff = le16_to_cpu(attr->nres.run_off); + ++ if (roff > le32_to_cpu(attr->size)) { ++ err = -EINVAL; ++ goto out; ++ } ++ + run_unpack_ex(RUN_DEALLOCATE, sbi, ni->mi.rno, svcn, + evcn1 - 1, svcn, Add2Ptr(attr, roff), + le32_to_cpu(attr->size) - roff); +diff --git a/fs/ntfs3/attrlist.c b/fs/ntfs3/attrlist.c +index bad6d8a849a24..c0c6bcbc8c05c 100644 +--- a/fs/ntfs3/attrlist.c ++++ b/fs/ntfs3/attrlist.c +@@ -68,6 +68,11 @@ int ntfs_load_attr_list(struct ntfs_inode *ni, struct ATTRIB *attr) + + run_init(&ni->attr_list.run); + ++ if (run_off > le32_to_cpu(attr->size)) { ++ err = -EINVAL; ++ goto out; ++ } ++ + err = run_unpack_ex(&ni->attr_list.run, ni->mi.sbi, ni->mi.rno, + 0, le64_to_cpu(attr->nres.evcn), 0, + Add2Ptr(attr, run_off), +diff --git a/fs/ntfs3/bitmap.c b/fs/ntfs3/bitmap.c +index e92bbd754365e..45f95c1cb2584 100644 +--- a/fs/ntfs3/bitmap.c ++++ b/fs/ntfs3/bitmap.c +@@ -661,7 +661,7 @@ int wnd_init(struct wnd_bitmap *wnd, struct super_block *sb, size_t nbits) + if (!wnd->bits_last) + wnd->bits_last = wbits; + +- wnd->free_bits = kcalloc(wnd->nwnd, sizeof(u16), GFP_NOFS); ++ wnd->free_bits = kcalloc(wnd->nwnd, sizeof(u16), GFP_NOFS | __GFP_NOWARN); + if (!wnd->free_bits) + return -ENOMEM; + +@@ -1424,7 +1424,7 @@ int ntfs_trim_fs(struct ntfs_sb_info *sbi, struct fstrim_range *range) + + down_read_nested(&wnd->rw_lock, BITMAP_MUTEX_CLUSTERS); + +- for (; iw < wnd->nbits; iw++, wbit = 0) { ++ for (; iw < wnd->nwnd; iw++, wbit = 0) { + CLST lcn_wnd = iw * wbits; + struct buffer_head *bh; + +diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c +index 381a38a06ec22..b1b476fb7229b 100644 +--- a/fs/ntfs3/frecord.c ++++ b/fs/ntfs3/frecord.c +@@ -568,6 +568,12 @@ static int ni_repack(struct ntfs_inode *ni) + } + + roff = le16_to_cpu(attr->nres.run_off); ++ ++ if (roff > le32_to_cpu(attr->size)) { ++ err = -EINVAL; ++ break; ++ } ++ + err = run_unpack(&run, sbi, ni->mi.rno, svcn, evcn, svcn, + Add2Ptr(attr, roff), + le32_to_cpu(attr->size) - roff); +@@ -1589,6 +1595,9 @@ int ni_delete_all(struct ntfs_inode *ni) + asize = le32_to_cpu(attr->size); + roff = le16_to_cpu(attr->nres.run_off); + ++ if (roff > asize) ++ return -EINVAL; ++ + /* run==1 means unpack and deallocate. */ + run_unpack_ex(RUN_DEALLOCATE, sbi, ni->mi.rno, svcn, evcn, svcn, + Add2Ptr(attr, roff), asize - roff); +@@ -2291,6 +2300,11 @@ remove_wof: + asize = le32_to_cpu(attr->size); + roff = le16_to_cpu(attr->nres.run_off); + ++ if (roff > asize) { ++ err = -EINVAL; ++ goto out; ++ } ++ + /*run==1 Means unpack and deallocate. */ + run_unpack_ex(RUN_DEALLOCATE, sbi, ni->mi.rno, svcn, evcn, svcn, + Add2Ptr(attr, roff), asize - roff); +diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c +index 0d611a6c5511f..c662d2a519072 100644 +--- a/fs/ntfs3/fslog.c ++++ b/fs/ntfs3/fslog.c +@@ -1132,7 +1132,7 @@ static int read_log_page(struct ntfs_log *log, u32 vbo, + return -EINVAL; + + if (!*buffer) { +- to_free = kmalloc(bytes, GFP_NOFS); ++ to_free = kmalloc(log->page_size, GFP_NOFS); + if (!to_free) + return -ENOMEM; + *buffer = to_free; +@@ -1180,10 +1180,7 @@ static int log_read_rst(struct ntfs_log *log, u32 l_size, bool first, + struct restart_info *info) + { + u32 skip, vbo; +- struct RESTART_HDR *r_page = kmalloc(DefaultLogPageSize, GFP_NOFS); +- +- if (!r_page) +- return -ENOMEM; ++ struct RESTART_HDR *r_page = NULL; + + /* Determine which restart area we are looking for. */ + if (first) { +@@ -1197,7 +1194,6 @@ static int log_read_rst(struct ntfs_log *log, u32 l_size, bool first, + /* Loop continuously until we succeed. */ + for (; vbo < l_size; vbo = 2 * vbo + skip, skip = 0) { + bool usa_error; +- u32 sys_page_size; + bool brst, bchk; + struct RESTART_AREA *ra; + +@@ -1251,24 +1247,6 @@ static int log_read_rst(struct ntfs_log *log, u32 l_size, bool first, + goto check_result; + } + +- /* Read the entire restart area. */ +- sys_page_size = le32_to_cpu(r_page->sys_page_size); +- if (DefaultLogPageSize != sys_page_size) { +- kfree(r_page); +- r_page = kzalloc(sys_page_size, GFP_NOFS); +- if (!r_page) +- return -ENOMEM; +- +- if (read_log_page(log, vbo, +- (struct RECORD_PAGE_HDR **)&r_page, +- &usa_error)) { +- /* Ignore any errors. */ +- kfree(r_page); +- r_page = NULL; +- continue; +- } +- } +- + if (is_client_area_valid(r_page, usa_error)) { + info->valid_page = true; + ra = Add2Ptr(r_page, le16_to_cpu(r_page->ra_off)); +@@ -2727,6 +2705,9 @@ static inline bool check_attr(const struct MFT_REC *rec, + return false; + } + ++ if (run_off > asize) ++ return false; ++ + if (run_unpack(NULL, sbi, 0, svcn, evcn, svcn, + Add2Ptr(attr, run_off), asize - run_off) < 0) { + return false; +@@ -4771,6 +4752,12 @@ fake_attr: + u16 roff = le16_to_cpu(attr->nres.run_off); + CLST svcn = le64_to_cpu(attr->nres.svcn); + ++ if (roff > t32) { ++ kfree(oa->attr); ++ oa->attr = NULL; ++ goto fake_attr; ++ } ++ + err = run_unpack(&oa->run0, sbi, inode->i_ino, svcn, + le64_to_cpu(attr->nres.evcn), svcn, + Add2Ptr(attr, roff), t32 - roff); +diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c +index 4ed15f64b17f6..b6e22bcb929ba 100644 +--- a/fs/ntfs3/fsntfs.c ++++ b/fs/ntfs3/fsntfs.c +@@ -1849,9 +1849,10 @@ int ntfs_security_init(struct ntfs_sb_info *sbi) + goto out; + } + +- root_sdh = resident_data(attr); ++ root_sdh = resident_data_ex(attr, sizeof(struct INDEX_ROOT)); + if (root_sdh->type != ATTR_ZERO || +- root_sdh->rule != NTFS_COLLATION_TYPE_SECURITY_HASH) { ++ root_sdh->rule != NTFS_COLLATION_TYPE_SECURITY_HASH || ++ offsetof(struct INDEX_ROOT, ihdr) + root_sdh->ihdr.used > attr->res.data_size) { + err = -EINVAL; + goto out; + } +@@ -1867,9 +1868,10 @@ int ntfs_security_init(struct ntfs_sb_info *sbi) + goto out; + } + +- root_sii = resident_data(attr); ++ root_sii = resident_data_ex(attr, sizeof(struct INDEX_ROOT)); + if (root_sii->type != ATTR_ZERO || +- root_sii->rule != NTFS_COLLATION_TYPE_UINT) { ++ root_sii->rule != NTFS_COLLATION_TYPE_UINT || ++ offsetof(struct INDEX_ROOT, ihdr) + root_sii->ihdr.used > attr->res.data_size) { + err = -EINVAL; + goto out; + } +diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c +index 440328147e7e3..c27b4fe575136 100644 +--- a/fs/ntfs3/index.c ++++ b/fs/ntfs3/index.c +@@ -1017,6 +1017,12 @@ ok: + err = 0; + } + ++ /* check for index header length */ ++ if (offsetof(struct INDEX_BUFFER, ihdr) + ib->ihdr.used > bytes) { ++ err = -EINVAL; ++ goto out; ++ } ++ + in->index = ib; + *node = in; + +diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c +index d5a3afbbbfd8c..e352aa37330cd 100644 +--- a/fs/ntfs3/inode.c ++++ b/fs/ntfs3/inode.c +@@ -129,6 +129,9 @@ next_attr: + rsize = attr->non_res ? 0 : le32_to_cpu(attr->res.data_size); + asize = le32_to_cpu(attr->size); + ++ if (le16_to_cpu(attr->name_off) + attr->name_len > asize) ++ goto out; ++ + switch (attr->type) { + case ATTR_STD: + if (attr->non_res || +@@ -364,7 +367,13 @@ next_attr: + attr_unpack_run: + roff = le16_to_cpu(attr->nres.run_off); + ++ if (roff > asize) { ++ err = -EINVAL; ++ goto out; ++ } ++ + t64 = le64_to_cpu(attr->nres.svcn); ++ + err = run_unpack_ex(run, sbi, ino, t64, le64_to_cpu(attr->nres.evcn), + t64, Add2Ptr(attr, roff), asize - roff); + if (err < 0) +diff --git a/fs/ntfs3/record.c b/fs/ntfs3/record.c +index 7d2fac5ee2156..af1e4b364ea8e 100644 +--- a/fs/ntfs3/record.c ++++ b/fs/ntfs3/record.c +@@ -220,6 +220,11 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr) + return NULL; + } + ++ if (off + asize < off) { ++ /* overflow check */ ++ return NULL; ++ } ++ + attr = Add2Ptr(attr, asize); + off += asize; + } +@@ -260,6 +265,11 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr) + if (t16 + t32 > asize) + return NULL; + ++ if (attr->name_len && ++ le16_to_cpu(attr->name_off) + sizeof(short) * attr->name_len > t16) { ++ return NULL; ++ } ++ + return attr; + } + +diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c +index 47012c9bf505e..8e2fe0f69203b 100644 +--- a/fs/ntfs3/super.c ++++ b/fs/ntfs3/super.c +@@ -672,7 +672,7 @@ static u32 true_sectors_per_clst(const struct NTFS_BOOT *boot) + if (boot->sectors_per_clusters <= 0x80) + return boot->sectors_per_clusters; + if (boot->sectors_per_clusters >= 0xf4) /* limit shift to 2MB max */ +- return 1U << (0 - boot->sectors_per_clusters); ++ return 1U << -(s8)boot->sectors_per_clusters; + return -EINVAL; + } + +@@ -789,7 +789,7 @@ static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size, + : (u32)boot->record_size + << sbi->cluster_bits; + +- if (record_size > MAXIMUM_BYTES_PER_MFT) ++ if (record_size > MAXIMUM_BYTES_PER_MFT || record_size < SECTOR_SIZE) + goto out; + + sbi->record_bits = blksize_bits(record_size); +@@ -1141,7 +1141,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) + goto put_inode_out; + } + bytes = inode->i_size; +- sbi->def_table = t = kmalloc(bytes, GFP_NOFS); ++ sbi->def_table = t = kmalloc(bytes, GFP_NOFS | __GFP_NOWARN); + if (!t) { + err = -ENOMEM; + goto put_inode_out; +@@ -1260,9 +1260,9 @@ load_root: + ref.low = cpu_to_le32(MFT_REC_ROOT); + ref.seq = cpu_to_le16(MFT_REC_ROOT); + inode = ntfs_iget5(sb, &ref, &NAME_ROOT); +- if (IS_ERR(inode)) { ++ if (IS_ERR(inode) || !inode->i_op) { + ntfs_err(sb, "Failed to load root."); +- err = PTR_ERR(inode); ++ err = IS_ERR(inode) ? PTR_ERR(inode) : -EINVAL; + goto out; + } + +@@ -1281,6 +1281,7 @@ out: + * Free resources here. + * ntfs_fs_free will be called with fc->s_fs_info = NULL + */ ++ put_mount_options(sbi->options); + put_ntfs(sbi); + sb->s_fs_info = NULL; + +diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c +index 7de8718c68a90..ea582b4fe1d9d 100644 +--- a/fs/ntfs3/xattr.c ++++ b/fs/ntfs3/xattr.c +@@ -107,7 +107,7 @@ static int ntfs_read_ea(struct ntfs_inode *ni, struct EA_FULL **ea, + return -EFBIG; + + /* Allocate memory for packed Ea. */ +- ea_p = kmalloc(size + add_bytes, GFP_NOFS); ++ ea_p = kmalloc(size_add(size, add_bytes), GFP_NOFS); + if (!ea_p) + return -ENOMEM; + +diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c +index 126671e6caeda..3fb98b4569a28 100644 +--- a/fs/ocfs2/journal.c ++++ b/fs/ocfs2/journal.c +@@ -157,7 +157,7 @@ static void ocfs2_queue_replay_slots(struct ocfs2_super *osb, + replay_map->rm_state = REPLAY_DONE; + } + +-static void ocfs2_free_replay_slots(struct ocfs2_super *osb) ++void ocfs2_free_replay_slots(struct ocfs2_super *osb) + { + struct ocfs2_replay_map *replay_map = osb->replay_map; + +diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h +index 969d0aa287187..41c382f68529e 100644 +--- a/fs/ocfs2/journal.h ++++ b/fs/ocfs2/journal.h +@@ -150,6 +150,7 @@ int ocfs2_recovery_init(struct ocfs2_super *osb); + void ocfs2_recovery_exit(struct ocfs2_super *osb); + + int ocfs2_compute_replay_slots(struct ocfs2_super *osb); ++void ocfs2_free_replay_slots(struct ocfs2_super *osb); + /* + * Journal Control: + * Initialize, Load, Shutdown, Wipe a journal. +diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c +index 317126261523b..a8d5ca98fa57c 100644 +--- a/fs/ocfs2/stackglue.c ++++ b/fs/ocfs2/stackglue.c +@@ -669,6 +669,8 @@ static struct ctl_table_header *ocfs2_table_header; + + static int __init ocfs2_stack_glue_init(void) + { ++ int ret; ++ + strcpy(cluster_stack_name, OCFS2_STACK_PLUGIN_O2CB); + + ocfs2_table_header = register_sysctl("fs/ocfs2/nm", ocfs2_nm_table); +@@ -678,7 +680,11 @@ static int __init ocfs2_stack_glue_init(void) + return -ENOMEM; /* or something. */ + } + +- return ocfs2_sysfs_init(); ++ ret = ocfs2_sysfs_init(); ++ if (ret) ++ unregister_sysctl_table(ocfs2_table_header); ++ ++ return ret; + } + + static void __exit ocfs2_stack_glue_exit(void) +diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c +index 42c993e53924f..0b0e6a1321018 100644 +--- a/fs/ocfs2/super.c ++++ b/fs/ocfs2/super.c +@@ -1159,6 +1159,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) + out_dismount: + atomic_set(&osb->vol_state, VOLUME_DISABLED); + wake_up(&osb->osb_mount_event); ++ ocfs2_free_replay_slots(osb); + ocfs2_dismount_volume(sb, 1); + goto out; + +@@ -1822,12 +1823,14 @@ static int ocfs2_mount_volume(struct super_block *sb) + status = ocfs2_truncate_log_init(osb); + if (status < 0) { + mlog_errno(status); +- goto out_system_inodes; ++ goto out_check_volume; + } + + ocfs2_super_unlock(osb, 1); + return 0; + ++out_check_volume: ++ ocfs2_free_replay_slots(osb); + out_system_inodes: + if (osb->local_alloc_state == OCFS2_LA_ENABLED) + ocfs2_shutdown_local_alloc(osb); +diff --git a/fs/orangefs/orangefs-debugfs.c b/fs/orangefs/orangefs-debugfs.c +index 29eaa45443727..1b508f5433846 100644 +--- a/fs/orangefs/orangefs-debugfs.c ++++ b/fs/orangefs/orangefs-debugfs.c +@@ -194,15 +194,10 @@ void orangefs_debugfs_init(int debug_mask) + */ + static void orangefs_kernel_debug_init(void) + { +- int rc = -ENOMEM; +- char *k_buffer = NULL; ++ static char k_buffer[ORANGEFS_MAX_DEBUG_STRING_LEN] = { }; + + gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__); + +- k_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); +- if (!k_buffer) +- goto out; +- + if (strlen(kernel_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) { + strcpy(k_buffer, kernel_debug_string); + strcat(k_buffer, "\n"); +@@ -213,15 +208,14 @@ static void orangefs_kernel_debug_init(void) + + debugfs_create_file(ORANGEFS_KMOD_DEBUG_FILE, 0444, debug_dir, k_buffer, + &kernel_debug_fops); +- +-out: +- gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc); + } + + + void orangefs_debugfs_cleanup(void) + { + debugfs_remove_recursive(debug_dir); ++ kfree(debug_help_string); ++ debug_help_string = NULL; + } + + /* open ORANGEFS_KMOD_DEBUG_HELP_FILE */ +@@ -297,18 +291,13 @@ static int help_show(struct seq_file *m, void *v) + /* + * initialize the client-debug file. + */ +-static int orangefs_client_debug_init(void) ++static void orangefs_client_debug_init(void) + { + +- int rc = -ENOMEM; +- char *c_buffer = NULL; ++ static char c_buffer[ORANGEFS_MAX_DEBUG_STRING_LEN] = { }; + + gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__); + +- c_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); +- if (!c_buffer) +- goto out; +- + if (strlen(client_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) { + strcpy(c_buffer, client_debug_string); + strcat(c_buffer, "\n"); +@@ -322,13 +311,6 @@ static int orangefs_client_debug_init(void) + debug_dir, + c_buffer, + &kernel_debug_fops); +- +- rc = 0; +- +-out: +- +- gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc); +- return rc; + } + + /* open ORANGEFS_KMOD_DEBUG_FILE or ORANGEFS_CLIENT_DEBUG_FILE.*/ +@@ -671,6 +653,7 @@ int orangefs_prepare_debugfs_help_string(int at_boot) + memset(debug_help_string, 0, DEBUG_HELP_STRING_SIZE); + strlcat(debug_help_string, new, string_size); + mutex_unlock(&orangefs_help_file_lock); ++ kfree(new); + } + + rc = 0; +diff --git a/fs/orangefs/orangefs-mod.c b/fs/orangefs/orangefs-mod.c +index cd7297815f91e..5ab741c60b7e2 100644 +--- a/fs/orangefs/orangefs-mod.c ++++ b/fs/orangefs/orangefs-mod.c +@@ -141,7 +141,7 @@ static int __init orangefs_init(void) + gossip_err("%s: could not initialize device subsystem %d!\n", + __func__, + ret); +- goto cleanup_device; ++ goto cleanup_sysfs; + } + + ret = register_filesystem(&orangefs_fs_type); +@@ -152,11 +152,11 @@ static int __init orangefs_init(void) + goto out; + } + +- orangefs_sysfs_exit(); +- +-cleanup_device: + orangefs_dev_cleanup(); + ++cleanup_sysfs: ++ orangefs_sysfs_exit(); ++ + sysfs_init_failed: + orangefs_debugfs_cleanup(); + +diff --git a/fs/orangefs/orangefs-sysfs.c b/fs/orangefs/orangefs-sysfs.c +index de80b62553bb1..be4ba03a01a0f 100644 +--- a/fs/orangefs/orangefs-sysfs.c ++++ b/fs/orangefs/orangefs-sysfs.c +@@ -896,9 +896,18 @@ static struct attribute *orangefs_default_attrs[] = { + }; + ATTRIBUTE_GROUPS(orangefs_default); + ++static struct kobject *orangefs_obj; ++ ++static void orangefs_obj_release(struct kobject *kobj) ++{ ++ kfree(orangefs_obj); ++ orangefs_obj = NULL; ++} ++ + static struct kobj_type orangefs_ktype = { + .sysfs_ops = &orangefs_sysfs_ops, + .default_groups = orangefs_default_groups, ++ .release = orangefs_obj_release, + }; + + static struct orangefs_attribute acache_hard_limit_attribute = +@@ -934,9 +943,18 @@ static struct attribute *acache_orangefs_default_attrs[] = { + }; + ATTRIBUTE_GROUPS(acache_orangefs_default); + ++static struct kobject *acache_orangefs_obj; ++ ++static void acache_orangefs_obj_release(struct kobject *kobj) ++{ ++ kfree(acache_orangefs_obj); ++ acache_orangefs_obj = NULL; ++} ++ + static struct kobj_type acache_orangefs_ktype = { + .sysfs_ops = &orangefs_sysfs_ops, + .default_groups = acache_orangefs_default_groups, ++ .release = acache_orangefs_obj_release, + }; + + static struct orangefs_attribute capcache_hard_limit_attribute = +@@ -972,9 +990,18 @@ static struct attribute *capcache_orangefs_default_attrs[] = { + }; + ATTRIBUTE_GROUPS(capcache_orangefs_default); + ++static struct kobject *capcache_orangefs_obj; ++ ++static void capcache_orangefs_obj_release(struct kobject *kobj) ++{ ++ kfree(capcache_orangefs_obj); ++ capcache_orangefs_obj = NULL; ++} ++ + static struct kobj_type capcache_orangefs_ktype = { + .sysfs_ops = &orangefs_sysfs_ops, + .default_groups = capcache_orangefs_default_groups, ++ .release = capcache_orangefs_obj_release, + }; + + static struct orangefs_attribute ccache_hard_limit_attribute = +@@ -1010,9 +1037,18 @@ static struct attribute *ccache_orangefs_default_attrs[] = { + }; + ATTRIBUTE_GROUPS(ccache_orangefs_default); + ++static struct kobject *ccache_orangefs_obj; ++ ++static void ccache_orangefs_obj_release(struct kobject *kobj) ++{ ++ kfree(ccache_orangefs_obj); ++ ccache_orangefs_obj = NULL; ++} ++ + static struct kobj_type ccache_orangefs_ktype = { + .sysfs_ops = &orangefs_sysfs_ops, + .default_groups = ccache_orangefs_default_groups, ++ .release = ccache_orangefs_obj_release, + }; + + static struct orangefs_attribute ncache_hard_limit_attribute = +@@ -1048,9 +1084,18 @@ static struct attribute *ncache_orangefs_default_attrs[] = { + }; + ATTRIBUTE_GROUPS(ncache_orangefs_default); + ++static struct kobject *ncache_orangefs_obj; ++ ++static void ncache_orangefs_obj_release(struct kobject *kobj) ++{ ++ kfree(ncache_orangefs_obj); ++ ncache_orangefs_obj = NULL; ++} ++ + static struct kobj_type ncache_orangefs_ktype = { + .sysfs_ops = &orangefs_sysfs_ops, + .default_groups = ncache_orangefs_default_groups, ++ .release = ncache_orangefs_obj_release, + }; + + static struct orangefs_attribute pc_acache_attribute = +@@ -1079,9 +1124,18 @@ static struct attribute *pc_orangefs_default_attrs[] = { + }; + ATTRIBUTE_GROUPS(pc_orangefs_default); + ++static struct kobject *pc_orangefs_obj; ++ ++static void pc_orangefs_obj_release(struct kobject *kobj) ++{ ++ kfree(pc_orangefs_obj); ++ pc_orangefs_obj = NULL; ++} ++ + static struct kobj_type pc_orangefs_ktype = { + .sysfs_ops = &orangefs_sysfs_ops, + .default_groups = pc_orangefs_default_groups, ++ .release = pc_orangefs_obj_release, + }; + + static struct orangefs_attribute stats_reads_attribute = +@@ -1103,19 +1157,20 @@ static struct attribute *stats_orangefs_default_attrs[] = { + }; + ATTRIBUTE_GROUPS(stats_orangefs_default); + ++static struct kobject *stats_orangefs_obj; ++ ++static void stats_orangefs_obj_release(struct kobject *kobj) ++{ ++ kfree(stats_orangefs_obj); ++ stats_orangefs_obj = NULL; ++} ++ + static struct kobj_type stats_orangefs_ktype = { + .sysfs_ops = &orangefs_sysfs_ops, + .default_groups = stats_orangefs_default_groups, ++ .release = stats_orangefs_obj_release, + }; + +-static struct kobject *orangefs_obj; +-static struct kobject *acache_orangefs_obj; +-static struct kobject *capcache_orangefs_obj; +-static struct kobject *ccache_orangefs_obj; +-static struct kobject *ncache_orangefs_obj; +-static struct kobject *pc_orangefs_obj; +-static struct kobject *stats_orangefs_obj; +- + int orangefs_sysfs_init(void) + { + int rc = -EINVAL; +diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c +index 6b03457f72bb1..c3032cef391ef 100644 +--- a/fs/overlayfs/dir.c ++++ b/fs/overlayfs/dir.c +@@ -592,28 +592,42 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode, + goto out_revert_creds; + } + +- err = -ENOMEM; +- override_cred = prepare_creds(); +- if (override_cred) { ++ if (!attr->hardlink) { ++ err = -ENOMEM; ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ goto out_revert_creds; ++ /* ++ * In the creation cases(create, mkdir, mknod, symlink), ++ * ovl should transfer current's fs{u,g}id to underlying ++ * fs. Because underlying fs want to initialize its new ++ * inode owner using current's fs{u,g}id. And in this ++ * case, the @inode is a new inode that is initialized ++ * in inode_init_owner() to current's fs{u,g}id. So use ++ * the inode's i_{u,g}id to override the cred's fs{u,g}id. ++ * ++ * But in the other hardlink case, ovl_link() does not ++ * create a new inode, so just use the ovl mounter's ++ * fs{u,g}id. ++ */ + override_cred->fsuid = inode->i_uid; + override_cred->fsgid = inode->i_gid; +- if (!attr->hardlink) { +- err = security_dentry_create_files_as(dentry, +- attr->mode, &dentry->d_name, old_cred, +- override_cred); +- if (err) { +- put_cred(override_cred); +- goto out_revert_creds; +- } ++ err = security_dentry_create_files_as(dentry, ++ attr->mode, &dentry->d_name, old_cred, ++ override_cred); ++ if (err) { ++ put_cred(override_cred); ++ goto out_revert_creds; + } + put_cred(override_creds(override_cred)); + put_cred(override_cred); +- +- if (!ovl_dentry_is_whiteout(dentry)) +- err = ovl_create_upper(dentry, inode, attr); +- else +- err = ovl_create_over_whiteout(dentry, inode, attr); + } ++ ++ if (!ovl_dentry_is_whiteout(dentry)) ++ err = ovl_create_upper(dentry, inode, attr); ++ else ++ err = ovl_create_over_whiteout(dentry, inode, attr); ++ + out_revert_creds: + revert_creds(old_cred); + return err; +diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c +index a1a22f58ba183..6011f955436ba 100644 +--- a/fs/overlayfs/file.c ++++ b/fs/overlayfs/file.c +@@ -96,6 +96,7 @@ static int ovl_change_flags(struct file *file, unsigned int flags) + + spin_lock(&file->f_lock); + file->f_flags = (file->f_flags & ~OVL_SETFL_MASK) | flags; ++ file->f_iocb_flags = iocb_flags(file); + spin_unlock(&file->f_lock); + + return 0; +@@ -517,9 +518,16 @@ static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len + const struct cred *old_cred; + int ret; + ++ inode_lock(inode); ++ /* Update mode */ ++ ovl_copyattr(inode); ++ ret = file_remove_privs(file); ++ if (ret) ++ goto out_unlock; ++ + ret = ovl_real_fdget(file, &real); + if (ret) +- return ret; ++ goto out_unlock; + + old_cred = ovl_override_creds(file_inode(file)->i_sb); + ret = vfs_fallocate(real.file, mode, offset, len); +@@ -530,6 +538,9 @@ static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len + + fdput(real); + ++out_unlock: ++ inode_unlock(inode); ++ + return ret; + } + +@@ -567,14 +578,23 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, + const struct cred *old_cred; + loff_t ret; + ++ inode_lock(inode_out); ++ if (op != OVL_DEDUPE) { ++ /* Update mode */ ++ ovl_copyattr(inode_out); ++ ret = file_remove_privs(file_out); ++ if (ret) ++ goto out_unlock; ++ } ++ + ret = ovl_real_fdget(file_out, &real_out); + if (ret) +- return ret; ++ goto out_unlock; + + ret = ovl_real_fdget(file_in, &real_in); + if (ret) { + fdput(real_out); +- return ret; ++ goto out_unlock; + } + + old_cred = ovl_override_creds(file_inode(file_out)->i_sb); +@@ -603,6 +623,9 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, + fdput(real_in); + fdput(real_out); + ++out_unlock: ++ inode_unlock(inode_out); ++ + return ret; + } + +diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c +index a29a8afe9b262..3d14a3f1465d1 100644 +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -139,11 +139,16 @@ static int ovl_dentry_revalidate_common(struct dentry *dentry, + unsigned int flags, bool weak) + { + struct ovl_entry *oe = dentry->d_fsdata; ++ struct inode *inode = d_inode_rcu(dentry); + struct dentry *upper; + unsigned int i; + int ret = 1; + +- upper = ovl_dentry_upper(dentry); ++ /* Careful in RCU mode */ ++ if (!inode) ++ return -ECHILD; ++ ++ upper = ovl_i_dentry_upper(inode); + if (upper) + ret = ovl_revalidate_real(upper, flags, weak); + +diff --git a/fs/pnode.c b/fs/pnode.c +index 1106137c747a3..468e4e65a615d 100644 +--- a/fs/pnode.c ++++ b/fs/pnode.c +@@ -244,7 +244,7 @@ static int propagate_one(struct mount *m) + } + do { + struct mount *parent = last_source->mnt_parent; +- if (last_source == first_source) ++ if (peers(last_source, first_source)) + break; + done = parent->mnt_master == p; + if (done && peers(n, parent)) +diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig +index 8adabde685f13..c49d554cc9ae9 100644 +--- a/fs/pstore/Kconfig ++++ b/fs/pstore/Kconfig +@@ -126,6 +126,7 @@ config PSTORE_CONSOLE + config PSTORE_PMSG + bool "Log user space messages" + depends on PSTORE ++ select RT_MUTEXES + help + When the option is enabled, pstore will export a character + interface /dev/pmsg0 to log user space messages. On reboot +diff --git a/fs/pstore/pmsg.c b/fs/pstore/pmsg.c +index d8542ec2f38c6..18cf94b597e05 100644 +--- a/fs/pstore/pmsg.c ++++ b/fs/pstore/pmsg.c +@@ -7,9 +7,10 @@ + #include <linux/device.h> + #include <linux/fs.h> + #include <linux/uaccess.h> ++#include <linux/rtmutex.h> + #include "internal.h" + +-static DEFINE_MUTEX(pmsg_lock); ++static DEFINE_RT_MUTEX(pmsg_lock); + + static ssize_t write_pmsg(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +@@ -28,9 +29,9 @@ static ssize_t write_pmsg(struct file *file, const char __user *buf, + if (!access_ok(buf, count)) + return -EFAULT; + +- mutex_lock(&pmsg_lock); ++ rt_mutex_lock(&pmsg_lock); + ret = psinfo->write_user(&record, buf); +- mutex_unlock(&pmsg_lock); ++ rt_mutex_unlock(&pmsg_lock); + return ret ? ret : count; + } + +diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c +index fefe3d391d3af..f3fa3625d772c 100644 +--- a/fs/pstore/ram.c ++++ b/fs/pstore/ram.c +@@ -670,7 +670,7 @@ static int ramoops_parse_dt(struct platform_device *pdev, + field = value; \ + } + +- parse_u32("mem-type", pdata->record_size, pdata->mem_type); ++ parse_u32("mem-type", pdata->mem_type, pdata->mem_type); + parse_u32("record-size", pdata->record_size, 0); + parse_u32("console-size", pdata->console_size, 0); + parse_u32("ftrace-size", pdata->ftrace_size, 0); +@@ -735,6 +735,7 @@ static int ramoops_probe(struct platform_device *pdev) + /* Make sure we didn't get bogus platform data pointer. */ + if (!pdata) { + pr_err("NULL platform data\n"); ++ err = -EINVAL; + goto fail_out; + } + +@@ -742,6 +743,7 @@ static int ramoops_probe(struct platform_device *pdev) + !pdata->ftrace_size && !pdata->pmsg_size)) { + pr_err("The memory size and the record/console size must be " + "non-zero\n"); ++ err = -EINVAL; + goto fail_out; + } + +diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c +index a89e33719fcf2..8bf09886e7e66 100644 +--- a/fs/pstore/ram_core.c ++++ b/fs/pstore/ram_core.c +@@ -439,7 +439,11 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size, + phys_addr_t addr = page_start + i * PAGE_SIZE; + pages[i] = pfn_to_page(addr >> PAGE_SHIFT); + } +- vaddr = vmap(pages, page_count, VM_MAP, prot); ++ /* ++ * VM_IOREMAP used here to bypass this region during vread() ++ * and kmap_atomic() (i.e. kcore) to avoid __va() failures. ++ */ ++ vaddr = vmap(pages, page_count, VM_MAP | VM_IOREMAP, prot); + kfree(pages); + + /* +diff --git a/fs/pstore/zone.c b/fs/pstore/zone.c +index 017d0d4ad3295..2770746bb7aa1 100644 +--- a/fs/pstore/zone.c ++++ b/fs/pstore/zone.c +@@ -761,7 +761,7 @@ static inline int notrace psz_kmsg_write_record(struct psz_context *cxt, + /* avoid destroying old data, allocate a new one */ + len = zone->buffer_size + sizeof(*zone->buffer); + zone->oldbuf = zone->buffer; +- zone->buffer = kzalloc(len, GFP_KERNEL); ++ zone->buffer = kzalloc(len, GFP_ATOMIC); + if (!zone->buffer) { + zone->buffer = zone->oldbuf; + return -ENOMEM; +diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c +index 3d7a35d6a18bc..b916859992ec8 100644 +--- a/fs/reiserfs/namei.c ++++ b/fs/reiserfs/namei.c +@@ -696,6 +696,7 @@ static int reiserfs_create(struct user_namespace *mnt_userns, struct inode *dir, + + out_failed: + reiserfs_write_unlock(dir->i_sb); ++ reiserfs_security_free(&security); + return retval; + } + +@@ -779,6 +780,7 @@ static int reiserfs_mknod(struct user_namespace *mnt_userns, struct inode *dir, + + out_failed: + reiserfs_write_unlock(dir->i_sb); ++ reiserfs_security_free(&security); + return retval; + } + +@@ -878,6 +880,7 @@ static int reiserfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir, + retval = journal_end(&th); + out_failed: + reiserfs_write_unlock(dir->i_sb); ++ reiserfs_security_free(&security); + return retval; + } + +@@ -1194,6 +1197,7 @@ static int reiserfs_symlink(struct user_namespace *mnt_userns, + retval = journal_end(&th); + out_failed: + reiserfs_write_unlock(parent_dir->i_sb); ++ reiserfs_security_free(&security); + return retval; + } + +diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c +index 8965c8e5e172b..857a65b057264 100644 +--- a/fs/reiserfs/xattr_security.c ++++ b/fs/reiserfs/xattr_security.c +@@ -50,6 +50,7 @@ int reiserfs_security_init(struct inode *dir, struct inode *inode, + int error; + + sec->name = NULL; ++ sec->value = NULL; + + /* Don't add selinux attributes on xattrs - they'll never get used */ + if (IS_PRIVATE(dir)) +@@ -95,7 +96,6 @@ int reiserfs_security_write(struct reiserfs_transaction_handle *th, + + void reiserfs_security_free(struct reiserfs_security_handle *sec) + { +- kfree(sec->name); + kfree(sec->value); + sec->name = NULL; + sec->value = NULL; +diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c +index d4ec9bb97de95..3b8567564e7e4 100644 +--- a/fs/sysv/itree.c ++++ b/fs/sysv/itree.c +@@ -438,7 +438,7 @@ static unsigned sysv_nblocks(struct super_block *s, loff_t size) + res += blocks; + direct = 1; + } +- return blocks; ++ return res; + } + + int sysv_getattr(struct user_namespace *mnt_userns, const struct path *path, +diff --git a/fs/udf/inode.c b/fs/udf/inode.c +index dce6ae9ae306c..f713d108f21d3 100644 +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -439,6 +439,12 @@ static int udf_get_block(struct inode *inode, sector_t block, + iinfo->i_next_alloc_goal++; + } + ++ /* ++ * Block beyond EOF and prealloc extents? Just discard preallocation ++ * as it is not useful and complicates things. ++ */ ++ if (((loff_t)block) << inode->i_blkbits > iinfo->i_lenExtents) ++ udf_discard_prealloc(inode); + udf_clear_extent_cache(inode); + phys = inode_getblk(inode, block, &err, &new); + if (!phys) +@@ -488,8 +494,6 @@ static int udf_do_extend_file(struct inode *inode, + uint32_t add; + int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK); + struct super_block *sb = inode->i_sb; +- struct kernel_lb_addr prealloc_loc = {}; +- uint32_t prealloc_len = 0; + struct udf_inode_info *iinfo; + int err; + +@@ -510,19 +514,6 @@ static int udf_do_extend_file(struct inode *inode, + ~(sb->s_blocksize - 1); + } + +- /* Last extent are just preallocated blocks? */ +- if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == +- EXT_NOT_RECORDED_ALLOCATED) { +- /* Save the extent so that we can reattach it to the end */ +- prealloc_loc = last_ext->extLocation; +- prealloc_len = last_ext->extLength; +- /* Mark the extent as a hole */ +- last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | +- (last_ext->extLength & UDF_EXTENT_LENGTH_MASK); +- last_ext->extLocation.logicalBlockNum = 0; +- last_ext->extLocation.partitionReferenceNum = 0; +- } +- + /* Can we merge with the previous extent? */ + if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == + EXT_NOT_RECORDED_NOT_ALLOCATED) { +@@ -550,7 +541,7 @@ static int udf_do_extend_file(struct inode *inode, + * more extents, we may need to enter possible following + * empty indirect extent. + */ +- if (new_block_bytes || prealloc_len) ++ if (new_block_bytes) + udf_next_aext(inode, last_pos, &tmploc, &tmplen, 0); + } + +@@ -584,17 +575,6 @@ static int udf_do_extend_file(struct inode *inode, + } + + out: +- /* Do we have some preallocated blocks saved? */ +- if (prealloc_len) { +- err = udf_add_aext(inode, last_pos, &prealloc_loc, +- prealloc_len, 1); +- if (err) +- return err; +- last_ext->extLocation = prealloc_loc; +- last_ext->extLength = prealloc_len; +- count++; +- } +- + /* last_pos should point to the last written extent... */ + if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) + last_pos->offset -= sizeof(struct short_ad); +@@ -610,13 +590,17 @@ out: + static void udf_do_extend_final_block(struct inode *inode, + struct extent_position *last_pos, + struct kernel_long_ad *last_ext, +- uint32_t final_block_len) ++ uint32_t new_elen) + { +- struct super_block *sb = inode->i_sb; + uint32_t added_bytes; + +- added_bytes = final_block_len - +- (last_ext->extLength & (sb->s_blocksize - 1)); ++ /* ++ * Extent already large enough? It may be already rounded up to block ++ * size... ++ */ ++ if (new_elen <= (last_ext->extLength & UDF_EXTENT_LENGTH_MASK)) ++ return; ++ added_bytes = (last_ext->extLength & UDF_EXTENT_LENGTH_MASK) - new_elen; + last_ext->extLength += added_bytes; + UDF_I(inode)->i_lenExtents += added_bytes; + +@@ -633,12 +617,12 @@ static int udf_extend_file(struct inode *inode, loff_t newsize) + int8_t etype; + struct super_block *sb = inode->i_sb; + sector_t first_block = newsize >> sb->s_blocksize_bits, offset; +- unsigned long partial_final_block; ++ loff_t new_elen; + int adsize; + struct udf_inode_info *iinfo = UDF_I(inode); + struct kernel_long_ad extent; + int err = 0; +- int within_final_block; ++ bool within_last_ext; + + if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) + adsize = sizeof(struct short_ad); +@@ -647,8 +631,17 @@ static int udf_extend_file(struct inode *inode, loff_t newsize) + else + BUG(); + ++ /* ++ * When creating hole in file, just don't bother with preserving ++ * preallocation. It likely won't be very useful anyway. ++ */ ++ udf_discard_prealloc(inode); ++ + etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset); +- within_final_block = (etype != -1); ++ within_last_ext = (etype != -1); ++ /* We don't expect extents past EOF... */ ++ WARN_ON_ONCE(within_last_ext && ++ elen > ((loff_t)offset + 1) << inode->i_blkbits); + + if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) || + (epos.bh && epos.offset == sizeof(struct allocExtDesc))) { +@@ -664,19 +657,17 @@ static int udf_extend_file(struct inode *inode, loff_t newsize) + extent.extLength |= etype << 30; + } + +- partial_final_block = newsize & (sb->s_blocksize - 1); ++ new_elen = ((loff_t)offset << inode->i_blkbits) | ++ (newsize & (sb->s_blocksize - 1)); + + /* File has extent covering the new size (could happen when extending + * inside a block)? + */ +- if (within_final_block) { ++ if (within_last_ext) { + /* Extending file within the last file block */ +- udf_do_extend_final_block(inode, &epos, &extent, +- partial_final_block); ++ udf_do_extend_final_block(inode, &epos, &extent, new_elen); + } else { +- loff_t add = ((loff_t)offset << sb->s_blocksize_bits) | +- partial_final_block; +- err = udf_do_extend_file(inode, &epos, &extent, add); ++ err = udf_do_extend_file(inode, &epos, &extent, new_elen); + } + + if (err < 0) +@@ -777,10 +768,11 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, + goto out_free; + } + +- /* Are we beyond EOF? */ ++ /* Are we beyond EOF and preallocated extent? */ + if (etype == -1) { + int ret; + loff_t hole_len; ++ + isBeyondEOF = true; + if (count) { + if (c) +diff --git a/fs/udf/namei.c b/fs/udf/namei.c +index ae7bc13a5298a..7c95c549dd64e 100644 +--- a/fs/udf/namei.c ++++ b/fs/udf/namei.c +@@ -1091,8 +1091,9 @@ static int udf_rename(struct user_namespace *mnt_userns, struct inode *old_dir, + return -EINVAL; + + ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi); +- if (IS_ERR(ofi)) { +- retval = PTR_ERR(ofi); ++ if (!ofi || IS_ERR(ofi)) { ++ if (IS_ERR(ofi)) ++ retval = PTR_ERR(ofi); + goto end_rename; + } + +@@ -1101,8 +1102,7 @@ static int udf_rename(struct user_namespace *mnt_userns, struct inode *old_dir, + + brelse(ofibh.sbh); + tloc = lelb_to_cpu(ocfi.icb.extLocation); +- if (!ofi || udf_get_lb_pblock(old_dir->i_sb, &tloc, 0) +- != old_inode->i_ino) ++ if (udf_get_lb_pblock(old_dir->i_sb, &tloc, 0) != old_inode->i_ino) + goto end_rename; + + nfi = udf_find_entry(new_dir, &new_dentry->d_name, &nfibh, &ncfi); +diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c +index 532cda99644ee..036ebd892b852 100644 +--- a/fs/udf/truncate.c ++++ b/fs/udf/truncate.c +@@ -120,60 +120,42 @@ void udf_truncate_tail_extent(struct inode *inode) + + void udf_discard_prealloc(struct inode *inode) + { +- struct extent_position epos = { NULL, 0, {0, 0} }; ++ struct extent_position epos = {}; ++ struct extent_position prev_epos = {}; + struct kernel_lb_addr eloc; + uint32_t elen; + uint64_t lbcount = 0; + int8_t etype = -1, netype; +- int adsize; + struct udf_inode_info *iinfo = UDF_I(inode); ++ int bsize = 1 << inode->i_blkbits; + + if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB || +- inode->i_size == iinfo->i_lenExtents) ++ ALIGN(inode->i_size, bsize) == ALIGN(iinfo->i_lenExtents, bsize)) + return; + +- if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) +- adsize = sizeof(struct short_ad); +- else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) +- adsize = sizeof(struct long_ad); +- else +- adsize = 0; +- + epos.block = iinfo->i_location; + + /* Find the last extent in the file */ +- while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) { +- etype = netype; ++ while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 0)) != -1) { ++ brelse(prev_epos.bh); ++ prev_epos = epos; ++ if (prev_epos.bh) ++ get_bh(prev_epos.bh); ++ ++ etype = udf_next_aext(inode, &epos, &eloc, &elen, 1); + lbcount += elen; + } + if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) { +- epos.offset -= adsize; + lbcount -= elen; +- extent_trunc(inode, &epos, &eloc, etype, elen, 0); +- if (!epos.bh) { +- iinfo->i_lenAlloc = +- epos.offset - +- udf_file_entry_alloc_offset(inode); +- mark_inode_dirty(inode); +- } else { +- struct allocExtDesc *aed = +- (struct allocExtDesc *)(epos.bh->b_data); +- aed->lengthAllocDescs = +- cpu_to_le32(epos.offset - +- sizeof(struct allocExtDesc)); +- if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || +- UDF_SB(inode->i_sb)->s_udfrev >= 0x0201) +- udf_update_tag(epos.bh->b_data, epos.offset); +- else +- udf_update_tag(epos.bh->b_data, +- sizeof(struct allocExtDesc)); +- mark_buffer_dirty_inode(epos.bh, inode); +- } ++ udf_delete_aext(inode, prev_epos); ++ udf_free_blocks(inode->i_sb, inode, &eloc, 0, ++ DIV_ROUND_UP(elen, 1 << inode->i_blkbits)); + } + /* This inode entry is in-memory only and thus we don't have to mark + * the inode dirty */ + iinfo->i_lenExtents = lbcount; + brelse(epos.bh); ++ brelse(prev_epos.bh); + } + + static void udf_update_alloc_ext_desc(struct inode *inode, +diff --git a/fs/xattr.c b/fs/xattr.c +index 61107b6bbed29..427b8cea1f968 100644 +--- a/fs/xattr.c ++++ b/fs/xattr.c +@@ -1140,7 +1140,7 @@ static int xattr_list_one(char **buffer, ssize_t *remaining_size, + ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs, + char *buffer, size_t size) + { +- bool trusted = capable(CAP_SYS_ADMIN); ++ bool trusted = ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN); + struct simple_xattr *xattr; + ssize_t remaining_size = size; + int err = 0; +diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h +index 56aee949c6fa2..4d830fc55a3df 100644 +--- a/include/drm/drm_connector.h ++++ b/include/drm/drm_connector.h +@@ -656,6 +656,12 @@ struct drm_display_info { + * @mso_pixel_overlap: eDP MSO segment pixel overlap, 0-8 pixels. + */ + u8 mso_pixel_overlap; ++ ++ /** ++ * @max_dsc_bpp: Maximum DSC target bitrate, if it is set to 0 the ++ * monitor's default value is used instead. ++ */ ++ u32 max_dsc_bpp; + }; + + int drm_display_info_set_bus_formats(struct drm_display_info *info, +diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h +index 17a0310e8aaaf..b7d3f3843f1e6 100644 +--- a/include/drm/ttm/ttm_tt.h ++++ b/include/drm/ttm/ttm_tt.h +@@ -88,7 +88,7 @@ struct ttm_tt { + #define TTM_TT_FLAG_EXTERNAL (1 << 2) + #define TTM_TT_FLAG_EXTERNAL_MAPPABLE (1 << 3) + +-#define TTM_TT_FLAG_PRIV_POPULATED (1 << 31) ++#define TTM_TT_FLAG_PRIV_POPULATED (1U << 31) + uint32_t page_flags; + /** @num_pages: Number of pages in the page array. */ + uint32_t num_pages; +diff --git a/include/dt-bindings/clock/imx8mn-clock.h b/include/dt-bindings/clock/imx8mn-clock.h +index 07b8a282c2682..04809edab33cf 100644 +--- a/include/dt-bindings/clock/imx8mn-clock.h ++++ b/include/dt-bindings/clock/imx8mn-clock.h +@@ -16,40 +16,48 @@ + #define IMX8MN_CLK_EXT4 7 + #define IMX8MN_AUDIO_PLL1_REF_SEL 8 + #define IMX8MN_AUDIO_PLL2_REF_SEL 9 +-#define IMX8MN_VIDEO_PLL1_REF_SEL 10 ++#define IMX8MN_VIDEO_PLL_REF_SEL 10 ++#define IMX8MN_VIDEO_PLL1_REF_SEL IMX8MN_VIDEO_PLL_REF_SEL + #define IMX8MN_DRAM_PLL_REF_SEL 11 + #define IMX8MN_GPU_PLL_REF_SEL 12 +-#define IMX8MN_VPU_PLL_REF_SEL 13 ++#define IMX8MN_M7_ALT_PLL_REF_SEL 13 ++#define IMX8MN_VPU_PLL_REF_SEL IMX8MN_M7_ALT_PLL_REF_SEL + #define IMX8MN_ARM_PLL_REF_SEL 14 + #define IMX8MN_SYS_PLL1_REF_SEL 15 + #define IMX8MN_SYS_PLL2_REF_SEL 16 + #define IMX8MN_SYS_PLL3_REF_SEL 17 + #define IMX8MN_AUDIO_PLL1 18 + #define IMX8MN_AUDIO_PLL2 19 +-#define IMX8MN_VIDEO_PLL1 20 ++#define IMX8MN_VIDEO_PLL 20 ++#define IMX8MN_VIDEO_PLL1 IMX8MN_VIDEO_PLL + #define IMX8MN_DRAM_PLL 21 + #define IMX8MN_GPU_PLL 22 +-#define IMX8MN_VPU_PLL 23 ++#define IMX8MN_M7_ALT_PLL 23 ++#define IMX8MN_VPU_PLL IMX8MN_M7_ALT_PLL + #define IMX8MN_ARM_PLL 24 + #define IMX8MN_SYS_PLL1 25 + #define IMX8MN_SYS_PLL2 26 + #define IMX8MN_SYS_PLL3 27 + #define IMX8MN_AUDIO_PLL1_BYPASS 28 + #define IMX8MN_AUDIO_PLL2_BYPASS 29 +-#define IMX8MN_VIDEO_PLL1_BYPASS 30 ++#define IMX8MN_VIDEO_PLL_BYPASS 30 ++#define IMX8MN_VIDEO_PLL1_BYPASS IMX8MN_VIDEO_PLL_BYPASS + #define IMX8MN_DRAM_PLL_BYPASS 31 + #define IMX8MN_GPU_PLL_BYPASS 32 +-#define IMX8MN_VPU_PLL_BYPASS 33 ++#define IMX8MN_M7_ALT_PLL_BYPASS 33 ++#define IMX8MN_VPU_PLL_BYPASS IMX8MN_M7_ALT_PLL_BYPASS + #define IMX8MN_ARM_PLL_BYPASS 34 + #define IMX8MN_SYS_PLL1_BYPASS 35 + #define IMX8MN_SYS_PLL2_BYPASS 36 + #define IMX8MN_SYS_PLL3_BYPASS 37 + #define IMX8MN_AUDIO_PLL1_OUT 38 + #define IMX8MN_AUDIO_PLL2_OUT 39 +-#define IMX8MN_VIDEO_PLL1_OUT 40 ++#define IMX8MN_VIDEO_PLL_OUT 40 ++#define IMX8MN_VIDEO_PLL1_OUT IMX8MN_VIDEO_PLL_OUT + #define IMX8MN_DRAM_PLL_OUT 41 + #define IMX8MN_GPU_PLL_OUT 42 +-#define IMX8MN_VPU_PLL_OUT 43 ++#define IMX8MN_M7_ALT_PLL_OUT 43 ++#define IMX8MN_VPU_PLL_OUT IMX8MN_M7_ALT_PLL_OUT + #define IMX8MN_ARM_PLL_OUT 44 + #define IMX8MN_SYS_PLL1_OUT 45 + #define IMX8MN_SYS_PLL2_OUT 46 +diff --git a/include/dt-bindings/clock/imx8mp-clock.h b/include/dt-bindings/clock/imx8mp-clock.h +index 9d5cc2ddde896..1417b7b1b7dfe 100644 +--- a/include/dt-bindings/clock/imx8mp-clock.h ++++ b/include/dt-bindings/clock/imx8mp-clock.h +@@ -324,8 +324,9 @@ + #define IMX8MP_CLK_CLKOUT2_SEL 317 + #define IMX8MP_CLK_CLKOUT2_DIV 318 + #define IMX8MP_CLK_CLKOUT2 319 ++#define IMX8MP_CLK_USB_SUSP 320 + +-#define IMX8MP_CLK_END 320 ++#define IMX8MP_CLK_END 321 + + #define IMX8MP_CLK_AUDIOMIX_SAI1_IPG 0 + #define IMX8MP_CLK_AUDIOMIX_SAI1_MCLK1 1 +diff --git a/include/linux/btf_ids.h b/include/linux/btf_ids.h +index 2aea877d644f8..2b98720084285 100644 +--- a/include/linux/btf_ids.h ++++ b/include/linux/btf_ids.h +@@ -204,7 +204,7 @@ extern struct btf_id_set8 name; + + #else + +-#define BTF_ID_LIST(name) static u32 __maybe_unused name[5]; ++#define BTF_ID_LIST(name) static u32 __maybe_unused name[16]; + #define BTF_ID(prefix, name) + #define BTF_ID_FLAGS(prefix, name, ...) + #define BTF_ID_UNUSED +diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h +index f60674692d365..ea2d919fd9c79 100644 +--- a/include/linux/debugfs.h ++++ b/include/linux/debugfs.h +@@ -45,7 +45,7 @@ struct debugfs_u32_array { + + extern struct dentry *arch_debugfs_dir; + +-#define DEFINE_DEBUGFS_ATTRIBUTE(__fops, __get, __set, __fmt) \ ++#define DEFINE_DEBUGFS_ATTRIBUTE_XSIGNED(__fops, __get, __set, __fmt, __is_signed) \ + static int __fops ## _open(struct inode *inode, struct file *file) \ + { \ + __simple_attr_check_format(__fmt, 0ull); \ +@@ -56,10 +56,16 @@ static const struct file_operations __fops = { \ + .open = __fops ## _open, \ + .release = simple_attr_release, \ + .read = debugfs_attr_read, \ +- .write = debugfs_attr_write, \ ++ .write = (__is_signed) ? debugfs_attr_write_signed : debugfs_attr_write, \ + .llseek = no_llseek, \ + } + ++#define DEFINE_DEBUGFS_ATTRIBUTE(__fops, __get, __set, __fmt) \ ++ DEFINE_DEBUGFS_ATTRIBUTE_XSIGNED(__fops, __get, __set, __fmt, false) ++ ++#define DEFINE_DEBUGFS_ATTRIBUTE_SIGNED(__fops, __get, __set, __fmt) \ ++ DEFINE_DEBUGFS_ATTRIBUTE_XSIGNED(__fops, __get, __set, __fmt, true) ++ + typedef struct vfsmount *(*debugfs_automount_t)(struct dentry *, void *); + + #if defined(CONFIG_DEBUG_FS) +@@ -102,6 +108,8 @@ ssize_t debugfs_attr_read(struct file *file, char __user *buf, + size_t len, loff_t *ppos); + ssize_t debugfs_attr_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos); ++ssize_t debugfs_attr_write_signed(struct file *file, const char __user *buf, ++ size_t len, loff_t *ppos); + + struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, + struct dentry *new_dir, const char *new_name); +@@ -254,6 +262,13 @@ static inline ssize_t debugfs_attr_write(struct file *file, + return -ENODEV; + } + ++static inline ssize_t debugfs_attr_write_signed(struct file *file, ++ const char __user *buf, ++ size_t len, loff_t *ppos) ++{ ++ return -ENODEV; ++} ++ + static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, + struct dentry *new_dir, char *new_name) + { +diff --git a/include/linux/eventfd.h b/include/linux/eventfd.h +index 30eb30d6909b0..36a486505b081 100644 +--- a/include/linux/eventfd.h ++++ b/include/linux/eventfd.h +@@ -40,6 +40,7 @@ struct file *eventfd_fget(int fd); + struct eventfd_ctx *eventfd_ctx_fdget(int fd); + struct eventfd_ctx *eventfd_ctx_fileget(struct file *file); + __u64 eventfd_signal(struct eventfd_ctx *ctx, __u64 n); ++__u64 eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n, unsigned mask); + int eventfd_ctx_remove_wait_queue(struct eventfd_ctx *ctx, wait_queue_entry_t *wait, + __u64 *cnt); + void eventfd_ctx_do_read(struct eventfd_ctx *ctx, __u64 *cnt); +@@ -61,7 +62,13 @@ static inline struct eventfd_ctx *eventfd_ctx_fdget(int fd) + return ERR_PTR(-ENOSYS); + } + +-static inline int eventfd_signal(struct eventfd_ctx *ctx, int n) ++static inline int eventfd_signal(struct eventfd_ctx *ctx, __u64 n) ++{ ++ return -ENOSYS; ++} ++ ++static inline int eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n, ++ unsigned mask) + { + return -ENOSYS; + } +diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h +index 1067a8450826b..5001a11258e4d 100644 +--- a/include/linux/fortify-string.h ++++ b/include/linux/fortify-string.h +@@ -18,7 +18,7 @@ void __write_overflow_field(size_t avail, size_t wanted) __compiletime_warning(" + + #define __compiletime_strlen(p) \ + ({ \ +- unsigned char *__p = (unsigned char *)(p); \ ++ char *__p = (char *)(p); \ + size_t __ret = SIZE_MAX; \ + size_t __p_size = __member_size(p); \ + if (__p_size != SIZE_MAX && \ +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 59ae95ddb6793..6b115bce14b98 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -3493,7 +3493,7 @@ void simple_transaction_set(struct file *file, size_t n); + * All attributes contain a text representation of a numeric value + * that are accessed with the get() and set() functions. + */ +-#define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt) \ ++#define DEFINE_SIMPLE_ATTRIBUTE_XSIGNED(__fops, __get, __set, __fmt, __is_signed) \ + static int __fops ## _open(struct inode *inode, struct file *file) \ + { \ + __simple_attr_check_format(__fmt, 0ull); \ +@@ -3504,10 +3504,16 @@ static const struct file_operations __fops = { \ + .open = __fops ## _open, \ + .release = simple_attr_release, \ + .read = simple_attr_read, \ +- .write = simple_attr_write, \ ++ .write = (__is_signed) ? simple_attr_write_signed : simple_attr_write, \ + .llseek = generic_file_llseek, \ + } + ++#define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt) \ ++ DEFINE_SIMPLE_ATTRIBUTE_XSIGNED(__fops, __get, __set, __fmt, false) ++ ++#define DEFINE_SIMPLE_ATTRIBUTE_SIGNED(__fops, __get, __set, __fmt) \ ++ DEFINE_SIMPLE_ATTRIBUTE_XSIGNED(__fops, __get, __set, __fmt, true) ++ + static inline __printf(1, 2) + void __simple_attr_check_format(const char *fmt, ...) + { +@@ -3522,6 +3528,8 @@ ssize_t simple_attr_read(struct file *file, char __user *buf, + size_t len, loff_t *ppos); + ssize_t simple_attr_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos); ++ssize_t simple_attr_write_signed(struct file *file, const char __user *buf, ++ size_t len, loff_t *ppos); + + struct ctl_table; + int __init list_bdev_fs_names(char *buf, size_t size); +diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h +index e230c7c46110a..c3618255b1504 100644 +--- a/include/linux/hisi_acc_qm.h ++++ b/include/linux/hisi_acc_qm.h +@@ -384,14 +384,14 @@ struct hisi_qp { + static inline int q_num_set(const char *val, const struct kernel_param *kp, + unsigned int device) + { +- struct pci_dev *pdev = pci_get_device(PCI_VENDOR_ID_HUAWEI, +- device, NULL); ++ struct pci_dev *pdev; + u32 n, q_num; + int ret; + + if (!val) + return -EINVAL; + ++ pdev = pci_get_device(PCI_VENDOR_ID_HUAWEI, device, NULL); + if (!pdev) { + q_num = min_t(u32, QM_QNUM_V1, QM_QNUM_V2); + pr_info("No device found currently, suppose queue number is %u\n", +@@ -401,6 +401,8 @@ static inline int q_num_set(const char *val, const struct kernel_param *kp, + q_num = QM_QNUM_V1; + else + q_num = QM_QNUM_V2; ++ ++ pci_dev_put(pdev); + } + + ret = kstrtou32(val, 10, &n); +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +index 3b42264333ef8..646f1da9f27e0 100644 +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -1341,6 +1341,8 @@ struct hv_ring_buffer_debug_info { + int hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info, + struct hv_ring_buffer_debug_info *debug_info); + ++bool hv_ringbuffer_spinlock_busy(struct vmbus_channel *channel); ++ + /* Vmbus interface */ + #define vmbus_driver_register(driver) \ + __vmbus_driver_register(driver, THIS_MODULE, KBUILD_MODNAME) +diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h +index 79690938d9a2d..d3088666f3f44 100644 +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -4594,7 +4594,7 @@ static inline u8 ieee80211_mle_common_size(const u8 *data) + return 0; + } + +- return common + mle->variable[0]; ++ return sizeof(*mle) + common + mle->variable[0]; + } + + /** +diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h +index 515ca09764fe4..bcbefb7574751 100644 +--- a/include/linux/iio/imu/adis.h ++++ b/include/linux/iio/imu/adis.h +@@ -402,9 +402,20 @@ static inline int adis_update_bits_base(struct adis *adis, unsigned int reg, + __adis_update_bits_base(adis, reg, mask, val, sizeof(val)); \ + }) + +-int adis_enable_irq(struct adis *adis, bool enable); + int __adis_check_status(struct adis *adis); + int __adis_initial_startup(struct adis *adis); ++int __adis_enable_irq(struct adis *adis, bool enable); ++ ++static inline int adis_enable_irq(struct adis *adis, bool enable) ++{ ++ int ret; ++ ++ mutex_lock(&adis->state_lock); ++ ret = __adis_enable_irq(adis, enable); ++ mutex_unlock(&adis->state_lock); ++ ++ return ret; ++} + + static inline int adis_check_status(struct adis *adis) + { +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index eddf8ee270e74..ba2bd604359d4 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -171,31 +171,38 @@ static inline bool dev_xmit_complete(int rc) + * (unsigned long) so they can be read and written atomically. + */ + ++#define NET_DEV_STAT(FIELD) \ ++ union { \ ++ unsigned long FIELD; \ ++ atomic_long_t __##FIELD; \ ++ } ++ + struct net_device_stats { +- unsigned long rx_packets; +- unsigned long tx_packets; +- unsigned long rx_bytes; +- unsigned long tx_bytes; +- unsigned long rx_errors; +- unsigned long tx_errors; +- unsigned long rx_dropped; +- unsigned long tx_dropped; +- unsigned long multicast; +- unsigned long collisions; +- unsigned long rx_length_errors; +- unsigned long rx_over_errors; +- unsigned long rx_crc_errors; +- unsigned long rx_frame_errors; +- unsigned long rx_fifo_errors; +- unsigned long rx_missed_errors; +- unsigned long tx_aborted_errors; +- unsigned long tx_carrier_errors; +- unsigned long tx_fifo_errors; +- unsigned long tx_heartbeat_errors; +- unsigned long tx_window_errors; +- unsigned long rx_compressed; +- unsigned long tx_compressed; ++ NET_DEV_STAT(rx_packets); ++ NET_DEV_STAT(tx_packets); ++ NET_DEV_STAT(rx_bytes); ++ NET_DEV_STAT(tx_bytes); ++ NET_DEV_STAT(rx_errors); ++ NET_DEV_STAT(tx_errors); ++ NET_DEV_STAT(rx_dropped); ++ NET_DEV_STAT(tx_dropped); ++ NET_DEV_STAT(multicast); ++ NET_DEV_STAT(collisions); ++ NET_DEV_STAT(rx_length_errors); ++ NET_DEV_STAT(rx_over_errors); ++ NET_DEV_STAT(rx_crc_errors); ++ NET_DEV_STAT(rx_frame_errors); ++ NET_DEV_STAT(rx_fifo_errors); ++ NET_DEV_STAT(rx_missed_errors); ++ NET_DEV_STAT(tx_aborted_errors); ++ NET_DEV_STAT(tx_carrier_errors); ++ NET_DEV_STAT(tx_fifo_errors); ++ NET_DEV_STAT(tx_heartbeat_errors); ++ NET_DEV_STAT(tx_window_errors); ++ NET_DEV_STAT(rx_compressed); ++ NET_DEV_STAT(tx_compressed); + }; ++#undef NET_DEV_STAT + + /* per-cpu stats, allocated on demand. + * Try to fit them in a single cache line, for dev_get_stats() sake. +@@ -5164,4 +5171,9 @@ extern struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly; + + extern struct net_device *blackhole_netdev; + ++/* Note: Avoid these macros in fast path, prefer per-cpu or per-queue counters. */ ++#define DEV_STATS_INC(DEV, FIELD) atomic_long_inc(&(DEV)->stats.__##FIELD) ++#define DEV_STATS_ADD(DEV, FIELD, VAL) \ ++ atomic_long_add((VAL), &(DEV)->stats.__##FIELD) ++ + #endif /* _LINUX_NETDEVICE_H */ +diff --git a/include/linux/nvme.h b/include/linux/nvme.h +index 050d7d0cd81b0..d9fbc5afeaf72 100644 +--- a/include/linux/nvme.h ++++ b/include/linux/nvme.h +@@ -7,6 +7,7 @@ + #ifndef _LINUX_NVME_H + #define _LINUX_NVME_H + ++#include <linux/bits.h> + #include <linux/types.h> + #include <linux/uuid.h> + +@@ -639,7 +640,7 @@ enum { + NVME_CMD_EFFECTS_NCC = 1 << 2, + NVME_CMD_EFFECTS_NIC = 1 << 3, + NVME_CMD_EFFECTS_CCC = 1 << 4, +- NVME_CMD_EFFECTS_CSE_MASK = 3 << 16, ++ NVME_CMD_EFFECTS_CSE_MASK = GENMASK(18, 16), + NVME_CMD_EFFECTS_UUID_SEL = 1 << 19, + }; + +diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h +index 81d6e4ec2294b..0260f5ea98fe1 100644 +--- a/include/linux/proc_fs.h ++++ b/include/linux/proc_fs.h +@@ -208,8 +208,10 @@ static inline void proc_remove(struct proc_dir_entry *de) {} + static inline int remove_proc_subtree(const char *name, struct proc_dir_entry *parent) { return 0; } + + #define proc_create_net_data(name, mode, parent, ops, state_size, data) ({NULL;}) ++#define proc_create_net_data_write(name, mode, parent, ops, write, state_size, data) ({NULL;}) + #define proc_create_net(name, mode, parent, state_size, ops) ({NULL;}) + #define proc_create_net_single(name, mode, parent, show, data) ({NULL;}) ++#define proc_create_net_single_write(name, mode, parent, show, write, data) ({NULL;}) + + static inline struct pid *tgid_pidfd_to_pid(const struct file *file) + { +diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h +index f9a7461e72b80..d3b4a3d4514ab 100644 +--- a/include/linux/regulator/driver.h ++++ b/include/linux/regulator/driver.h +@@ -687,7 +687,8 @@ static inline int regulator_err2notif(int err) + + + struct regulator_dev * +-regulator_register(const struct regulator_desc *regulator_desc, ++regulator_register(struct device *dev, ++ const struct regulator_desc *regulator_desc, + const struct regulator_config *config); + struct regulator_dev * + devm_regulator_register(struct device *dev, +diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h +index 70d6cb94e5802..84f787416a54d 100644 +--- a/include/linux/skmsg.h ++++ b/include/linux/skmsg.h +@@ -82,6 +82,7 @@ struct sk_psock { + u32 apply_bytes; + u32 cork_bytes; + u32 eval; ++ bool redir_ingress; /* undefined if sk_redir is null */ + struct sk_msg *cork; + struct sk_psock_progs progs; + #if IS_ENABLED(CONFIG_BPF_STREAM_PARSER) +diff --git a/include/linux/timerqueue.h b/include/linux/timerqueue.h +index 93884086f3924..adc80e29168ea 100644 +--- a/include/linux/timerqueue.h ++++ b/include/linux/timerqueue.h +@@ -35,7 +35,7 @@ struct timerqueue_node *timerqueue_getnext(struct timerqueue_head *head) + { + struct rb_node *leftmost = rb_first_cached(&head->rb_root); + +- return rb_entry(leftmost, struct timerqueue_node, node); ++ return rb_entry_safe(leftmost, struct timerqueue_node, node); + } + + static inline void timerqueue_init(struct timerqueue_node *node) +diff --git a/include/media/dvbdev.h b/include/media/dvbdev.h +index 2f6b0861322ae..ac60c9fcfe9a6 100644 +--- a/include/media/dvbdev.h ++++ b/include/media/dvbdev.h +@@ -126,6 +126,7 @@ struct dvb_adapter { + * struct dvb_device - represents a DVB device node + * + * @list_head: List head with all DVB devices ++ * @ref: reference counter + * @fops: pointer to struct file_operations + * @adapter: pointer to the adapter that holds this device node + * @type: type of the device, as defined by &enum dvb_device_type. +@@ -156,6 +157,7 @@ struct dvb_adapter { + */ + struct dvb_device { + struct list_head list_head; ++ struct kref ref; + const struct file_operations *fops; + struct dvb_adapter *adapter; + enum dvb_device_type type; +@@ -187,6 +189,20 @@ struct dvb_device { + void *priv; + }; + ++/** ++ * dvb_device_get - Increase dvb_device reference ++ * ++ * @dvbdev: pointer to struct dvb_device ++ */ ++struct dvb_device *dvb_device_get(struct dvb_device *dvbdev); ++ ++/** ++ * dvb_device_put - Decrease dvb_device reference ++ * ++ * @dvbdev: pointer to struct dvb_device ++ */ ++void dvb_device_put(struct dvb_device *dvbdev); ++ + /** + * dvb_register_adapter - Registers a new DVB adapter + * +@@ -231,29 +247,17 @@ int dvb_register_device(struct dvb_adapter *adap, + /** + * dvb_remove_device - Remove a registered DVB device + * +- * This does not free memory. To do that, call dvb_free_device(). ++ * This does not free memory. dvb_free_device() will do that when ++ * reference counter is empty + * + * @dvbdev: pointer to struct dvb_device + */ + void dvb_remove_device(struct dvb_device *dvbdev); + +-/** +- * dvb_free_device - Free memory occupied by a DVB device. +- * +- * Call dvb_unregister_device() before calling this function. +- * +- * @dvbdev: pointer to struct dvb_device +- */ +-void dvb_free_device(struct dvb_device *dvbdev); + + /** + * dvb_unregister_device - Unregisters a DVB device + * +- * This is a combination of dvb_remove_device() and dvb_free_device(). +- * Using this function is usually a mistake, and is often an indicator +- * for a use-after-free bug (when a userspace process keeps a file +- * handle to a detached device). +- * + * @dvbdev: pointer to struct dvb_device + */ + void dvb_unregister_device(struct dvb_device *dvbdev); +diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h +index 684f1cd287301..7a381fcef939d 100644 +--- a/include/net/bluetooth/hci.h ++++ b/include/net/bluetooth/hci.h +@@ -274,6 +274,26 @@ enum { + * during the hdev->setup vendor callback. + */ + HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, ++ ++ /* ++ * When this quirk is set, the HCI_OP_LE_SET_EXT_SCAN_ENABLE command is ++ * disabled. This is required for some Broadcom controllers which ++ * erroneously claim to support extended scanning. ++ * ++ * This quirk can be set before hci_register_dev is called or ++ * during the hdev->setup vendor callback. ++ */ ++ HCI_QUIRK_BROKEN_EXT_SCAN, ++ ++ /* ++ * When this quirk is set, the HCI_OP_GET_MWS_TRANSPORT_CONFIG command is ++ * disabled. This is required for some Broadcom controllers which ++ * erroneously claim to support MWS Transport Layer Configuration. ++ * ++ * This quirk can be set before hci_register_dev is called or ++ * during the hdev->setup vendor callback. ++ */ ++ HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG, + }; + + /* HCI device flags */ +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index c54bc71254afa..7f585e5dd71b8 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -1689,7 +1689,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn); + + /* Use ext scanning if set ext scan param and ext scan enable is supported */ + #define use_ext_scan(dev) (((dev)->commands[37] & 0x20) && \ +- ((dev)->commands[37] & 0x40)) ++ ((dev)->commands[37] & 0x40) && \ ++ !test_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &(dev)->quirks)) ++ + /* Use ext create connection if command is supported */ + #define use_ext_conn(dev) ((dev)->commands[37] & 0x80) + +@@ -1717,6 +1719,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn); + ((dev)->le_features[3] & HCI_LE_CIS_PERIPHERAL) + #define bis_capable(dev) ((dev)->le_features[3] & HCI_LE_ISO_BROADCASTER) + ++#define mws_transport_config_capable(dev) (((dev)->commands[30] & 0x08) && \ ++ (!test_bit(HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG, &(dev)->quirks))) ++ + /* ----- HCI protocols ----- */ + #define HCI_PROTO_DEFER 0x01 + +diff --git a/include/net/dst.h b/include/net/dst.h +index 00b479ce6b99c..d67fda89cd0fa 100644 +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -356,9 +356,8 @@ static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev, + static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev, + struct net *net) + { +- /* TODO : stats should be SMP safe */ +- dev->stats.rx_packets++; +- dev->stats.rx_bytes += skb->len; ++ DEV_STATS_INC(dev, rx_packets); ++ DEV_STATS_ADD(dev, rx_bytes, skb->len); + __skb_tunnel_rx(skb, dev, net); + } + +diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h +index ff1804a0c4692..1fca6a88114ad 100644 +--- a/include/net/ip_vs.h ++++ b/include/net/ip_vs.h +@@ -351,11 +351,11 @@ struct ip_vs_seq { + + /* counters per cpu */ + struct ip_vs_counters { +- __u64 conns; /* connections scheduled */ +- __u64 inpkts; /* incoming packets */ +- __u64 outpkts; /* outgoing packets */ +- __u64 inbytes; /* incoming bytes */ +- __u64 outbytes; /* outgoing bytes */ ++ u64_stats_t conns; /* connections scheduled */ ++ u64_stats_t inpkts; /* incoming packets */ ++ u64_stats_t outpkts; /* outgoing packets */ ++ u64_stats_t inbytes; /* incoming bytes */ ++ u64_stats_t outbytes; /* outgoing bytes */ + }; + /* Stats per cpu */ + struct ip_vs_cpu_stats { +diff --git a/include/net/mrp.h b/include/net/mrp.h +index 92cd3fb6cf9da..b28915ffea284 100644 +--- a/include/net/mrp.h ++++ b/include/net/mrp.h +@@ -124,6 +124,7 @@ struct mrp_applicant { + struct sk_buff *pdu; + struct rb_root mad; + struct rcu_head rcu; ++ bool active; + }; + + struct mrp_port { +diff --git a/include/net/sock_reuseport.h b/include/net/sock_reuseport.h +index efc9085c68927..6ec140b0a61bf 100644 +--- a/include/net/sock_reuseport.h ++++ b/include/net/sock_reuseport.h +@@ -16,6 +16,7 @@ struct sock_reuseport { + u16 max_socks; /* length of socks */ + u16 num_socks; /* elements in socks */ + u16 num_closed_socks; /* closed elements in socks */ ++ u16 incoming_cpu; + /* The last synq overflow event timestamp of this + * reuse->socks[] group. + */ +@@ -58,5 +59,6 @@ static inline bool reuseport_has_conns(struct sock *sk) + } + + void reuseport_has_conns_set(struct sock *sk); ++void reuseport_update_incoming_cpu(struct sock *sk, int val); + + #endif /* _SOCK_REUSEPORT_H */ +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 14d45661a84d8..5b70b241ce71b 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -2291,8 +2291,8 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore); + void tcp_bpf_clone(const struct sock *sk, struct sock *newsk); + #endif /* CONFIG_BPF_SYSCALL */ + +-int tcp_bpf_sendmsg_redir(struct sock *sk, struct sk_msg *msg, u32 bytes, +- int flags); ++int tcp_bpf_sendmsg_redir(struct sock *sk, bool ingress, ++ struct sk_msg *msg, u32 bytes, int flags); + #endif /* CONFIG_NET_SOCK_MSG */ + + #if !defined(CONFIG_BPF_SYSCALL) || !defined(CONFIG_NET_SOCK_MSG) +diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h +index 25ec8c181688d..eba23daf2c290 100644 +--- a/include/sound/hda_codec.h ++++ b/include/sound/hda_codec.h +@@ -258,6 +258,7 @@ struct hda_codec { + unsigned int link_down_at_suspend:1; /* link down at runtime suspend */ + unsigned int relaxed_resume:1; /* don't resume forcibly for jack */ + unsigned int forced_resume:1; /* forced resume for jack */ ++ unsigned int no_stream_clean_at_suspend:1; /* do not clean streams at suspend */ + + #ifdef CONFIG_PM + unsigned long power_on_acct; +diff --git a/include/sound/pcm.h b/include/sound/pcm.h +index 7b1a022910e8e..27040b472a4f6 100644 +--- a/include/sound/pcm.h ++++ b/include/sound/pcm.h +@@ -106,24 +106,24 @@ struct snd_pcm_ops { + #define SNDRV_PCM_POS_XRUN ((snd_pcm_uframes_t)-1) + + /* If you change this don't forget to change rates[] table in pcm_native.c */ +-#define SNDRV_PCM_RATE_5512 (1<<0) /* 5512Hz */ +-#define SNDRV_PCM_RATE_8000 (1<<1) /* 8000Hz */ +-#define SNDRV_PCM_RATE_11025 (1<<2) /* 11025Hz */ +-#define SNDRV_PCM_RATE_16000 (1<<3) /* 16000Hz */ +-#define SNDRV_PCM_RATE_22050 (1<<4) /* 22050Hz */ +-#define SNDRV_PCM_RATE_32000 (1<<5) /* 32000Hz */ +-#define SNDRV_PCM_RATE_44100 (1<<6) /* 44100Hz */ +-#define SNDRV_PCM_RATE_48000 (1<<7) /* 48000Hz */ +-#define SNDRV_PCM_RATE_64000 (1<<8) /* 64000Hz */ +-#define SNDRV_PCM_RATE_88200 (1<<9) /* 88200Hz */ +-#define SNDRV_PCM_RATE_96000 (1<<10) /* 96000Hz */ +-#define SNDRV_PCM_RATE_176400 (1<<11) /* 176400Hz */ +-#define SNDRV_PCM_RATE_192000 (1<<12) /* 192000Hz */ +-#define SNDRV_PCM_RATE_352800 (1<<13) /* 352800Hz */ +-#define SNDRV_PCM_RATE_384000 (1<<14) /* 384000Hz */ +- +-#define SNDRV_PCM_RATE_CONTINUOUS (1<<30) /* continuous range */ +-#define SNDRV_PCM_RATE_KNOT (1<<31) /* supports more non-continuos rates */ ++#define SNDRV_PCM_RATE_5512 (1U<<0) /* 5512Hz */ ++#define SNDRV_PCM_RATE_8000 (1U<<1) /* 8000Hz */ ++#define SNDRV_PCM_RATE_11025 (1U<<2) /* 11025Hz */ ++#define SNDRV_PCM_RATE_16000 (1U<<3) /* 16000Hz */ ++#define SNDRV_PCM_RATE_22050 (1U<<4) /* 22050Hz */ ++#define SNDRV_PCM_RATE_32000 (1U<<5) /* 32000Hz */ ++#define SNDRV_PCM_RATE_44100 (1U<<6) /* 44100Hz */ ++#define SNDRV_PCM_RATE_48000 (1U<<7) /* 48000Hz */ ++#define SNDRV_PCM_RATE_64000 (1U<<8) /* 64000Hz */ ++#define SNDRV_PCM_RATE_88200 (1U<<9) /* 88200Hz */ ++#define SNDRV_PCM_RATE_96000 (1U<<10) /* 96000Hz */ ++#define SNDRV_PCM_RATE_176400 (1U<<11) /* 176400Hz */ ++#define SNDRV_PCM_RATE_192000 (1U<<12) /* 192000Hz */ ++#define SNDRV_PCM_RATE_352800 (1U<<13) /* 352800Hz */ ++#define SNDRV_PCM_RATE_384000 (1U<<14) /* 384000Hz */ ++ ++#define SNDRV_PCM_RATE_CONTINUOUS (1U<<30) /* continuous range */ ++#define SNDRV_PCM_RATE_KNOT (1U<<31) /* supports more non-continuos rates */ + + #define SNDRV_PCM_RATE_8000_44100 (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_11025|\ + SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_22050|\ +diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h +index c6b372401c278..ff57e7f9914cc 100644 +--- a/include/trace/events/f2fs.h ++++ b/include/trace/events/f2fs.h +@@ -322,7 +322,7 @@ TRACE_EVENT(f2fs_unlink_enter, + __field(ino_t, ino) + __field(loff_t, size) + __field(blkcnt_t, blocks) +- __field(const char *, name) ++ __string(name, dentry->d_name.name) + ), + + TP_fast_assign( +@@ -330,7 +330,7 @@ TRACE_EVENT(f2fs_unlink_enter, + __entry->ino = dir->i_ino; + __entry->size = dir->i_size; + __entry->blocks = dir->i_blocks; +- __entry->name = dentry->d_name.name; ++ __assign_str(name, dentry->d_name.name); + ), + + TP_printk("dev = (%d,%d), dir ino = %lu, i_size = %lld, " +@@ -338,7 +338,7 @@ TRACE_EVENT(f2fs_unlink_enter, + show_dev_ino(__entry), + __entry->size, + (unsigned long long)__entry->blocks, +- __entry->name) ++ __get_str(name)) + ); + + DEFINE_EVENT(f2fs__inode_exit, f2fs_unlink_exit, +@@ -940,25 +940,29 @@ TRACE_EVENT(f2fs_direct_IO_enter, + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) +- __field(struct kiocb *, iocb) ++ __field(loff_t, ki_pos) ++ __field(int, ki_flags) ++ __field(u16, ki_ioprio) + __field(unsigned long, len) + __field(int, rw) + ), + + TP_fast_assign( +- __entry->dev = inode->i_sb->s_dev; +- __entry->ino = inode->i_ino; +- __entry->iocb = iocb; +- __entry->len = len; +- __entry->rw = rw; ++ __entry->dev = inode->i_sb->s_dev; ++ __entry->ino = inode->i_ino; ++ __entry->ki_pos = iocb->ki_pos; ++ __entry->ki_flags = iocb->ki_flags; ++ __entry->ki_ioprio = iocb->ki_ioprio; ++ __entry->len = len; ++ __entry->rw = rw; + ), + + TP_printk("dev = (%d,%d), ino = %lu pos = %lld len = %lu ki_flags = %x ki_ioprio = %x rw = %d", + show_dev_ino(__entry), +- __entry->iocb->ki_pos, ++ __entry->ki_pos, + __entry->len, +- __entry->iocb->ki_flags, +- __entry->iocb->ki_ioprio, ++ __entry->ki_flags, ++ __entry->ki_ioprio, + __entry->rw) + ); + +@@ -1407,19 +1411,19 @@ TRACE_EVENT(f2fs_write_checkpoint, + TP_STRUCT__entry( + __field(dev_t, dev) + __field(int, reason) +- __field(char *, msg) ++ __string(dest_msg, msg) + ), + + TP_fast_assign( + __entry->dev = sb->s_dev; + __entry->reason = reason; +- __entry->msg = msg; ++ __assign_str(dest_msg, msg); + ), + + TP_printk("dev = (%d,%d), checkpoint for %s, state = %s", + show_dev(__entry->dev), + show_cpreason(__entry->reason), +- __entry->msg) ++ __get_str(dest_msg)) + ); + + DECLARE_EVENT_CLASS(f2fs_discard, +diff --git a/include/trace/events/ib_mad.h b/include/trace/events/ib_mad.h +index 59363a083ecb9..d92691c78cff6 100644 +--- a/include/trace/events/ib_mad.h ++++ b/include/trace/events/ib_mad.h +@@ -49,7 +49,6 @@ DECLARE_EVENT_CLASS(ib_mad_send_template, + __field(int, retries_left) + __field(int, max_retries) + __field(int, retry) +- __field(u16, pkey) + ), + + TP_fast_assign( +@@ -89,7 +88,7 @@ DECLARE_EVENT_CLASS(ib_mad_send_template, + "hdr : base_ver 0x%x class 0x%x class_ver 0x%x " \ + "method 0x%x status 0x%x class_specific 0x%x tid 0x%llx " \ + "attr_id 0x%x attr_mod 0x%x => dlid 0x%08x sl %d "\ +- "pkey 0x%x rpqn 0x%x rqpkey 0x%x", ++ "rpqn 0x%x rqpkey 0x%x", + __entry->dev_index, __entry->port_num, __entry->qp_num, + __entry->agent_priv, be64_to_cpu(__entry->wrtid), + __entry->retries_left, __entry->max_retries, +@@ -100,7 +99,7 @@ DECLARE_EVENT_CLASS(ib_mad_send_template, + be16_to_cpu(__entry->class_specific), + be64_to_cpu(__entry->tid), be16_to_cpu(__entry->attr_id), + be32_to_cpu(__entry->attr_mod), +- be32_to_cpu(__entry->dlid), __entry->sl, __entry->pkey, ++ be32_to_cpu(__entry->dlid), __entry->sl, + __entry->rqpn, __entry->rqkey + ) + ); +@@ -204,7 +203,6 @@ TRACE_EVENT(ib_mad_recv_done_handler, + __field(u16, wc_status) + __field(u32, slid) + __field(u32, dev_index) +- __field(u16, pkey) + ), + + TP_fast_assign( +@@ -224,9 +222,6 @@ TRACE_EVENT(ib_mad_recv_done_handler, + __entry->slid = wc->slid; + __entry->src_qp = wc->src_qp; + __entry->sl = wc->sl; +- ib_query_pkey(qp_info->port_priv->device, +- qp_info->port_priv->port_num, +- wc->pkey_index, &__entry->pkey); + __entry->wc_status = wc->status; + ), + +@@ -234,7 +229,7 @@ TRACE_EVENT(ib_mad_recv_done_handler, + "base_ver 0x%02x class 0x%02x class_ver 0x%02x " \ + "method 0x%02x status 0x%04x class_specific 0x%04x " \ + "tid 0x%016llx attr_id 0x%04x attr_mod 0x%08x " \ +- "slid 0x%08x src QP%d, sl %d pkey 0x%04x", ++ "slid 0x%08x src QP%d, sl %d", + __entry->dev_index, __entry->port_num, __entry->qp_num, + __entry->wc_status, + __entry->length, +@@ -244,7 +239,7 @@ TRACE_EVENT(ib_mad_recv_done_handler, + be16_to_cpu(__entry->class_specific), + be64_to_cpu(__entry->tid), be16_to_cpu(__entry->attr_id), + be32_to_cpu(__entry->attr_mod), +- __entry->slid, __entry->src_qp, __entry->sl, __entry->pkey ++ __entry->slid, __entry->src_qp, __entry->sl + ) + ); + +diff --git a/include/uapi/linux/eventpoll.h b/include/uapi/linux/eventpoll.h +index 8a3432d0f0dcb..e687658843b1c 100644 +--- a/include/uapi/linux/eventpoll.h ++++ b/include/uapi/linux/eventpoll.h +@@ -41,6 +41,12 @@ + #define EPOLLMSG (__force __poll_t)0x00000400 + #define EPOLLRDHUP (__force __poll_t)0x00002000 + ++/* ++ * Internal flag - wakeup generated by io_uring, used to detect recursion back ++ * into the io_uring poll handler. ++ */ ++#define EPOLL_URING_WAKE ((__force __poll_t)(1U << 27)) ++ + /* Set exclusive wakeup mode for the target file descriptor */ + #define EPOLLEXCLUSIVE ((__force __poll_t)(1U << 28)) + +diff --git a/include/uapi/linux/idxd.h b/include/uapi/linux/idxd.h +index 2b9e7feba3f32..1d553bedbdb51 100644 +--- a/include/uapi/linux/idxd.h ++++ b/include/uapi/linux/idxd.h +@@ -295,7 +295,7 @@ struct dsa_completion_record { + }; + + uint32_t delta_rec_size; +- uint32_t crc_val; ++ uint64_t crc_val; + + /* DIF check & strip */ + struct { +diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h +index 2df3225b562fa..9d4c4078e8d00 100644 +--- a/include/uapi/linux/io_uring.h ++++ b/include/uapi/linux/io_uring.h +@@ -296,10 +296,28 @@ enum io_uring_op { + * + * IORING_RECVSEND_FIXED_BUF Use registered buffers, the index is stored in + * the buf_index field. ++ * ++ * IORING_SEND_ZC_REPORT_USAGE ++ * If set, SEND[MSG]_ZC should report ++ * the zerocopy usage in cqe.res ++ * for the IORING_CQE_F_NOTIF cqe. ++ * 0 is reported if zerocopy was actually possible. ++ * IORING_NOTIF_USAGE_ZC_COPIED if data was copied ++ * (at least partially). + */ + #define IORING_RECVSEND_POLL_FIRST (1U << 0) + #define IORING_RECV_MULTISHOT (1U << 1) + #define IORING_RECVSEND_FIXED_BUF (1U << 2) ++#define IORING_SEND_ZC_REPORT_USAGE (1U << 3) ++ ++/* ++ * cqe.res for IORING_CQE_F_NOTIF if ++ * IORING_SEND_ZC_REPORT_USAGE was requested ++ * ++ * It should be treated as a flag, all other ++ * bits of cqe.res should be treated as reserved! ++ */ ++#define IORING_NOTIF_USAGE_ZC_COPIED (1U << 31) + + /* + * accept flags stored in sqe->ioprio +diff --git a/include/uapi/linux/swab.h b/include/uapi/linux/swab.h +index 0723a9cce747c..01717181339eb 100644 +--- a/include/uapi/linux/swab.h ++++ b/include/uapi/linux/swab.h +@@ -3,7 +3,7 @@ + #define _UAPI_LINUX_SWAB_H + + #include <linux/types.h> +-#include <linux/compiler.h> ++#include <linux/stddef.h> + #include <asm/bitsperlong.h> + #include <asm/swab.h> + +diff --git a/include/uapi/rdma/hns-abi.h b/include/uapi/rdma/hns-abi.h +index f6fde06db4b4e..745790ce3c261 100644 +--- a/include/uapi/rdma/hns-abi.h ++++ b/include/uapi/rdma/hns-abi.h +@@ -85,11 +85,26 @@ struct hns_roce_ib_create_qp_resp { + __aligned_u64 dwqe_mmap_key; + }; + ++enum { ++ HNS_ROCE_EXSGE_FLAGS = 1 << 0, ++}; ++ ++enum { ++ HNS_ROCE_RSP_EXSGE_FLAGS = 1 << 0, ++}; ++ + struct hns_roce_ib_alloc_ucontext_resp { + __u32 qp_tab_size; + __u32 cqe_size; + __u32 srq_tab_size; + __u32 reserved; ++ __u32 config; ++ __u32 max_inline_data; ++}; ++ ++struct hns_roce_ib_alloc_ucontext { ++ __u32 config; ++ __u32 reserved; + }; + + struct hns_roce_ib_alloc_pd_resp { +diff --git a/include/uapi/sound/asequencer.h b/include/uapi/sound/asequencer.h +index 6d4a2c60808dd..00d2703e8fca5 100644 +--- a/include/uapi/sound/asequencer.h ++++ b/include/uapi/sound/asequencer.h +@@ -328,10 +328,10 @@ typedef int __bitwise snd_seq_client_type_t; + #define KERNEL_CLIENT ((__force snd_seq_client_type_t) 2) + + /* event filter flags */ +-#define SNDRV_SEQ_FILTER_BROADCAST (1<<0) /* accept broadcast messages */ +-#define SNDRV_SEQ_FILTER_MULTICAST (1<<1) /* accept multicast messages */ +-#define SNDRV_SEQ_FILTER_BOUNCE (1<<2) /* accept bounce event in error */ +-#define SNDRV_SEQ_FILTER_USE_EVENT (1<<31) /* use event filter */ ++#define SNDRV_SEQ_FILTER_BROADCAST (1U<<0) /* accept broadcast messages */ ++#define SNDRV_SEQ_FILTER_MULTICAST (1U<<1) /* accept multicast messages */ ++#define SNDRV_SEQ_FILTER_BOUNCE (1U<<2) /* accept bounce event in error */ ++#define SNDRV_SEQ_FILTER_USE_EVENT (1U<<31) /* use event filter */ + + struct snd_seq_client_info { + int client; /* client number to inquire */ +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index 61cd7ffd0f6aa..71f1cabb9f3d4 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -495,7 +495,7 @@ static void io_eventfd_ops(struct rcu_head *rcu) + int ops = atomic_xchg(&ev_fd->ops, 0); + + if (ops & BIT(IO_EVENTFD_OP_SIGNAL_BIT)) +- eventfd_signal(ev_fd->cq_ev_fd, 1); ++ eventfd_signal_mask(ev_fd->cq_ev_fd, 1, EPOLL_URING_WAKE); + + /* IO_EVENTFD_OP_FREE_BIT may not be set here depending on callback + * ordering in a race but if references are 0 we know we have to free +@@ -531,7 +531,7 @@ static void io_eventfd_signal(struct io_ring_ctx *ctx) + goto out; + + if (likely(eventfd_signal_allowed())) { +- eventfd_signal(ev_fd->cq_ev_fd, 1); ++ eventfd_signal_mask(ev_fd->cq_ev_fd, 1, EPOLL_URING_WAKE); + } else { + atomic_inc(&ev_fd->refs); + if (!atomic_fetch_or(BIT(IO_EVENTFD_OP_SIGNAL_BIT), &ev_fd->ops)) +@@ -1757,7 +1757,7 @@ static int io_issue_sqe(struct io_kiocb *req, unsigned int issue_flags) + return ret; + + /* If the op doesn't have a file, we're not polling for it */ +- if ((req->ctx->flags & IORING_SETUP_IOPOLL) && req->file) ++ if ((req->ctx->flags & IORING_SETUP_IOPOLL) && def->iopoll_queue) + io_iopoll_req_issued(req, issue_flags); + + return 0; +diff --git a/io_uring/io_uring.h b/io_uring/io_uring.h +index 50bc3af449534..4334cd30c423d 100644 +--- a/io_uring/io_uring.h ++++ b/io_uring/io_uring.h +@@ -4,6 +4,7 @@ + #include <linux/errno.h> + #include <linux/lockdep.h> + #include <linux/io_uring_types.h> ++#include <uapi/linux/eventpoll.h> + #include "io-wq.h" + #include "slist.h" + #include "filetable.h" +@@ -207,12 +208,18 @@ static inline void io_commit_cqring(struct io_ring_ctx *ctx) + static inline void __io_cqring_wake(struct io_ring_ctx *ctx) + { + /* +- * wake_up_all() may seem excessive, but io_wake_function() and +- * io_should_wake() handle the termination of the loop and only +- * wake as many waiters as we need to. ++ * Trigger waitqueue handler on all waiters on our waitqueue. This ++ * won't necessarily wake up all the tasks, io_should_wake() will make ++ * that decision. ++ * ++ * Pass in EPOLLIN|EPOLL_URING_WAKE as the poll wakeup key. The latter ++ * set in the mask so that if we recurse back into our own poll ++ * waitqueue handlers, we know we have a dependency between eventfd or ++ * epoll and should terminate multishot poll at that point. + */ + if (waitqueue_active(&ctx->cq_wait)) +- wake_up_all(&ctx->cq_wait); ++ __wake_up(&ctx->cq_wait, TASK_NORMAL, 0, ++ poll_to_key(EPOLL_URING_WAKE | EPOLLIN)); + } + + static inline void io_cqring_wake(struct io_ring_ctx *ctx) +diff --git a/io_uring/msg_ring.c b/io_uring/msg_ring.c +index 90d2fc6fd80e4..a49ccab262d53 100644 +--- a/io_uring/msg_ring.c ++++ b/io_uring/msg_ring.c +@@ -164,12 +164,10 @@ int io_msg_ring(struct io_kiocb *req, unsigned int issue_flags) + } + + done: ++ if (ret == -EAGAIN) ++ return -EAGAIN; + if (ret < 0) + req_set_fail(req); + io_req_set_res(req, ret, 0); +- /* put file to avoid an attempt to IOPOLL the req */ +- if (!(req->flags & REQ_F_FIXED_FILE)) +- io_put_file(req->file); +- req->file = NULL; + return IOU_OK; + } +diff --git a/io_uring/net.c b/io_uring/net.c +index ab83da7e80f04..bdd2b4e370b35 100644 +--- a/io_uring/net.c ++++ b/io_uring/net.c +@@ -479,6 +479,7 @@ static int __io_compat_recvmsg_copy_hdr(struct io_kiocb *req, + if (req->flags & REQ_F_BUFFER_SELECT) { + compat_ssize_t clen; + ++ iomsg->free_iov = NULL; + if (msg.msg_iovlen == 0) { + sr->len = 0; + } else if (msg.msg_iovlen > 1) { +@@ -805,10 +806,10 @@ retry_multishot: + goto retry_multishot; + + if (mshot_finished) { +- io_netmsg_recycle(req, issue_flags); + /* fast path, check for non-NULL to avoid function call */ + if (kmsg->free_iov) + kfree(kmsg->free_iov); ++ io_netmsg_recycle(req, issue_flags); + req->flags &= ~REQ_F_NEED_CLEANUP; + } + +@@ -937,7 +938,8 @@ int io_send_zc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) + + zc->flags = READ_ONCE(sqe->ioprio); + if (zc->flags & ~(IORING_RECVSEND_POLL_FIRST | +- IORING_RECVSEND_FIXED_BUF)) ++ IORING_RECVSEND_FIXED_BUF | ++ IORING_SEND_ZC_REPORT_USAGE)) + return -EINVAL; + notif = zc->notif = io_alloc_notif(ctx); + if (!notif) +@@ -955,6 +957,9 @@ int io_send_zc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) + req->imu = READ_ONCE(ctx->user_bufs[idx]); + io_req_set_rsrc_node(notif, ctx, 0); + } ++ if (zc->flags & IORING_SEND_ZC_REPORT_USAGE) { ++ io_notif_to_data(notif)->zc_report = true; ++ } + + if (req->opcode == IORING_OP_SEND_ZC) { + if (READ_ONCE(sqe->__pad3[0])) +diff --git a/io_uring/notif.c b/io_uring/notif.c +index e37c6569d82e8..4bfef10161fa0 100644 +--- a/io_uring/notif.c ++++ b/io_uring/notif.c +@@ -18,6 +18,10 @@ static void __io_notif_complete_tw(struct io_kiocb *notif, bool *locked) + __io_unaccount_mem(ctx->user, nd->account_pages); + nd->account_pages = 0; + } ++ ++ if (nd->zc_report && (nd->zc_copied || !nd->zc_used)) ++ notif->cqe.res |= IORING_NOTIF_USAGE_ZC_COPIED; ++ + io_req_task_complete(notif, locked); + } + +@@ -28,6 +32,13 @@ static void io_uring_tx_zerocopy_callback(struct sk_buff *skb, + struct io_notif_data *nd = container_of(uarg, struct io_notif_data, uarg); + struct io_kiocb *notif = cmd_to_io_kiocb(nd); + ++ if (nd->zc_report) { ++ if (success && !nd->zc_used && skb) ++ WRITE_ONCE(nd->zc_used, true); ++ else if (!success && !nd->zc_copied) ++ WRITE_ONCE(nd->zc_copied, true); ++ } ++ + if (refcount_dec_and_test(&uarg->refcnt)) { + notif->io_task_work.func = __io_notif_complete_tw; + io_req_task_work_add(notif); +@@ -55,6 +66,7 @@ struct io_kiocb *io_alloc_notif(struct io_ring_ctx *ctx) + nd->account_pages = 0; + nd->uarg.flags = SKBFL_ZEROCOPY_FRAG | SKBFL_DONT_ORPHAN; + nd->uarg.callback = io_uring_tx_zerocopy_callback; ++ nd->zc_report = nd->zc_used = nd->zc_copied = false; + refcount_set(&nd->uarg.refcnt, 1); + return notif; + } +diff --git a/io_uring/notif.h b/io_uring/notif.h +index 5b4d710c8ca54..4ae696273c781 100644 +--- a/io_uring/notif.h ++++ b/io_uring/notif.h +@@ -13,6 +13,9 @@ struct io_notif_data { + struct file *file; + struct ubuf_info uarg; + unsigned long account_pages; ++ bool zc_report; ++ bool zc_used; ++ bool zc_copied; + }; + + void io_notif_flush(struct io_kiocb *notif); +diff --git a/io_uring/opdef.c b/io_uring/opdef.c +index 83dc0f9ad3b2f..04dd2c983fce4 100644 +--- a/io_uring/opdef.c ++++ b/io_uring/opdef.c +@@ -63,6 +63,7 @@ const struct io_op_def io_op_defs[] = { + .audit_skip = 1, + .ioprio = 1, + .iopoll = 1, ++ .iopoll_queue = 1, + .async_size = sizeof(struct io_async_rw), + .name = "READV", + .prep = io_prep_rw, +@@ -80,6 +81,7 @@ const struct io_op_def io_op_defs[] = { + .audit_skip = 1, + .ioprio = 1, + .iopoll = 1, ++ .iopoll_queue = 1, + .async_size = sizeof(struct io_async_rw), + .name = "WRITEV", + .prep = io_prep_rw, +@@ -103,6 +105,7 @@ const struct io_op_def io_op_defs[] = { + .audit_skip = 1, + .ioprio = 1, + .iopoll = 1, ++ .iopoll_queue = 1, + .async_size = sizeof(struct io_async_rw), + .name = "READ_FIXED", + .prep = io_prep_rw, +@@ -118,6 +121,7 @@ const struct io_op_def io_op_defs[] = { + .audit_skip = 1, + .ioprio = 1, + .iopoll = 1, ++ .iopoll_queue = 1, + .async_size = sizeof(struct io_async_rw), + .name = "WRITE_FIXED", + .prep = io_prep_rw, +@@ -277,6 +281,7 @@ const struct io_op_def io_op_defs[] = { + .audit_skip = 1, + .ioprio = 1, + .iopoll = 1, ++ .iopoll_queue = 1, + .async_size = sizeof(struct io_async_rw), + .name = "READ", + .prep = io_prep_rw, +@@ -292,6 +297,7 @@ const struct io_op_def io_op_defs[] = { + .audit_skip = 1, + .ioprio = 1, + .iopoll = 1, ++ .iopoll_queue = 1, + .async_size = sizeof(struct io_async_rw), + .name = "WRITE", + .prep = io_prep_rw, +@@ -481,6 +487,7 @@ const struct io_op_def io_op_defs[] = { + .plug = 1, + .name = "URING_CMD", + .iopoll = 1, ++ .iopoll_queue = 1, + .async_size = uring_cmd_pdu_size(1), + .prep = io_uring_cmd_prep, + .issue = io_uring_cmd, +diff --git a/io_uring/opdef.h b/io_uring/opdef.h +index 3efe06d25473a..df7e13d9bfba7 100644 +--- a/io_uring/opdef.h ++++ b/io_uring/opdef.h +@@ -25,6 +25,8 @@ struct io_op_def { + unsigned ioprio : 1; + /* supports iopoll */ + unsigned iopoll : 1; ++ /* have to be put into the iopoll list */ ++ unsigned iopoll_queue : 1; + /* opcode specific path will handle ->async_data allocation if needed */ + unsigned manual_alloc : 1; + /* size of async data needed, if any */ +diff --git a/io_uring/poll.c b/io_uring/poll.c +index d9bf1767867e6..fded1445a803b 100644 +--- a/io_uring/poll.c ++++ b/io_uring/poll.c +@@ -429,6 +429,14 @@ static int io_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, + return 0; + + if (io_poll_get_ownership(req)) { ++ /* ++ * If we trigger a multishot poll off our own wakeup path, ++ * disable multishot as there is a circular dependency between ++ * CQ posting and triggering the event. ++ */ ++ if (mask & EPOLL_URING_WAKE) ++ poll->events |= EPOLLONESHOT; ++ + /* optional, saves extra locking for removal in tw handler */ + if (mask && poll->events & EPOLLONESHOT) { + list_del_init(&poll->wait.entry); +diff --git a/io_uring/timeout.c b/io_uring/timeout.c +index e8a8c20994805..06200fe73a044 100644 +--- a/io_uring/timeout.c ++++ b/io_uring/timeout.c +@@ -72,10 +72,12 @@ static bool io_kill_timeout(struct io_kiocb *req, int status) + __cold void io_flush_timeouts(struct io_ring_ctx *ctx) + __must_hold(&ctx->completion_lock) + { +- u32 seq = ctx->cached_cq_tail - atomic_read(&ctx->cq_timeouts); ++ u32 seq; + struct io_timeout *timeout, *tmp; + + spin_lock_irq(&ctx->timeout_lock); ++ seq = ctx->cached_cq_tail - atomic_read(&ctx->cq_timeouts); ++ + list_for_each_entry_safe(timeout, tmp, &ctx->timeout_list, list) { + struct io_kiocb *req = cmd_to_io_kiocb(timeout); + u32 events_needed, events_got; +diff --git a/ipc/mqueue.c b/ipc/mqueue.c +index 467a194b8a2ec..d09aa1c1e3e65 100644 +--- a/ipc/mqueue.c ++++ b/ipc/mqueue.c +@@ -1726,7 +1726,8 @@ static int __init init_mqueue_fs(void) + + if (!setup_mq_sysctls(&init_ipc_ns)) { + pr_warn("sysctl registration failed\n"); +- return -ENOMEM; ++ error = -ENOMEM; ++ goto out_kmem; + } + + error = register_filesystem(&mqueue_fs_type); +@@ -1744,8 +1745,9 @@ static int __init init_mqueue_fs(void) + out_filesystem: + unregister_filesystem(&mqueue_fs_type); + out_sysctl: +- kmem_cache_destroy(mqueue_inode_cachep); + retire_mq_sysctls(&init_ipc_ns); ++out_kmem: ++ kmem_cache_destroy(mqueue_inode_cachep); + return error; + } + +diff --git a/kernel/Makefile b/kernel/Makefile +index d754e0be1176d..ebc692242b68b 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -41,9 +41,6 @@ UBSAN_SANITIZE_kcov.o := n + KMSAN_SANITIZE_kcov.o := n + CFLAGS_kcov.o := $(call cc-option, -fno-conserve-stack) -fno-stack-protector + +-# Don't instrument error handlers +-CFLAGS_REMOVE_cfi.o := $(CC_FLAGS_CFI) +- + obj-y += sched/ + obj-y += locking/ + obj-y += power/ +diff --git a/kernel/acct.c b/kernel/acct.c +index 62200d799b9b0..034a26daabb2e 100644 +--- a/kernel/acct.c ++++ b/kernel/acct.c +@@ -350,6 +350,8 @@ static comp_t encode_comp_t(unsigned long value) + exp++; + } + ++ if (exp > (((comp_t) ~0U) >> MANTSIZE)) ++ return (comp_t) ~0U; + /* + * Clean it up and polish it off. + */ +diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c +index 35c07afac924e..efdbba2a0230e 100644 +--- a/kernel/bpf/btf.c ++++ b/kernel/bpf/btf.c +@@ -4481,6 +4481,11 @@ static int btf_func_proto_check(struct btf_verifier_env *env, + break; + } + ++ if (btf_type_is_resolve_source_only(arg_type)) { ++ btf_verifier_log_type(env, t, "Invalid arg#%u", i + 1); ++ return -EINVAL; ++ } ++ + if (args[i].name_off && + (!btf_name_offset_valid(btf, args[i].name_off) || + !btf_name_valid_identifier(btf, args[i].name_off))) { +diff --git a/kernel/bpf/cgroup_iter.c b/kernel/bpf/cgroup_iter.c +index 9fcf09f2ef00f..c187a9e62bdbb 100644 +--- a/kernel/bpf/cgroup_iter.c ++++ b/kernel/bpf/cgroup_iter.c +@@ -164,16 +164,30 @@ static int cgroup_iter_seq_init(void *priv, struct bpf_iter_aux_info *aux) + struct cgroup_iter_priv *p = (struct cgroup_iter_priv *)priv; + struct cgroup *cgrp = aux->cgroup.start; + ++ /* bpf_iter_attach_cgroup() has already acquired an extra reference ++ * for the start cgroup, but the reference may be released after ++ * cgroup_iter_seq_init(), so acquire another reference for the ++ * start cgroup. ++ */ + p->start_css = &cgrp->self; ++ css_get(p->start_css); + p->terminate = false; + p->visited_all = false; + p->order = aux->cgroup.order; + return 0; + } + ++static void cgroup_iter_seq_fini(void *priv) ++{ ++ struct cgroup_iter_priv *p = (struct cgroup_iter_priv *)priv; ++ ++ css_put(p->start_css); ++} ++ + static const struct bpf_iter_seq_info cgroup_iter_seq_info = { + .seq_ops = &cgroup_iter_seq_ops, + .init_seq_private = cgroup_iter_seq_init, ++ .fini_seq_private = cgroup_iter_seq_fini, + .seq_priv_size = sizeof(struct cgroup_iter_priv), + }; + +diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c +index 7b373a5e861f4..439ed7e5a82b8 100644 +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -3504,9 +3504,9 @@ static int bpf_prog_attach(const union bpf_attr *attr) + case BPF_PROG_TYPE_LSM: + if (ptype == BPF_PROG_TYPE_LSM && + prog->expected_attach_type != BPF_LSM_CGROUP) +- return -EINVAL; +- +- ret = cgroup_bpf_prog_attach(attr, ptype, prog); ++ ret = -EINVAL; ++ else ++ ret = cgroup_bpf_prog_attach(attr, ptype, prog); + break; + default: + ret = -EINVAL; +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 264b3dc714cc4..242fe307032f1 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -1008,9 +1008,9 @@ static void *copy_array(void *dst, const void *src, size_t n, size_t size, gfp_t + if (unlikely(check_mul_overflow(n, size, &bytes))) + return NULL; + +- if (ksize(dst) < bytes) { ++ if (ksize(dst) < ksize(src)) { + kfree(dst); +- dst = kmalloc_track_caller(bytes, flags); ++ dst = kmalloc_track_caller(kmalloc_size_roundup(bytes), flags); + if (!dst) + return NULL; + } +@@ -1027,12 +1027,14 @@ out: + */ + static void *realloc_array(void *arr, size_t old_n, size_t new_n, size_t size) + { ++ size_t alloc_size; + void *new_arr; + + if (!new_n || old_n == new_n) + goto out; + +- new_arr = krealloc_array(arr, new_n, size, GFP_KERNEL); ++ alloc_size = kmalloc_size_roundup(size_mul(new_n, size)); ++ new_arr = krealloc(arr, alloc_size, GFP_KERNEL); + if (!new_arr) { + kfree(arr); + return NULL; +@@ -2504,9 +2506,11 @@ static int push_jmp_history(struct bpf_verifier_env *env, + { + u32 cnt = cur->jmp_history_cnt; + struct bpf_idx_pair *p; ++ size_t alloc_size; + + cnt++; +- p = krealloc(cur->jmp_history, cnt * sizeof(*p), GFP_USER); ++ alloc_size = kmalloc_size_roundup(size_mul(cnt, sizeof(*p))); ++ p = krealloc(cur->jmp_history, alloc_size, GFP_USER); + if (!p) + return -ENOMEM; + p[cnt - 1].idx = env->insn_idx; +@@ -2768,7 +2772,7 @@ static void mark_all_scalars_precise(struct bpf_verifier_env *env, + } + } + +-static int __mark_chain_precision(struct bpf_verifier_env *env, int regno, ++static int __mark_chain_precision(struct bpf_verifier_env *env, int frame, int regno, + int spi) + { + struct bpf_verifier_state *st = env->cur_state; +@@ -2785,7 +2789,7 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno, + if (!env->bpf_capable) + return 0; + +- func = st->frame[st->curframe]; ++ func = st->frame[frame]; + if (regno >= 0) { + reg = &func->regs[regno]; + if (reg->type != SCALAR_VALUE) { +@@ -2866,7 +2870,7 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno, + break; + + new_marks = false; +- func = st->frame[st->curframe]; ++ func = st->frame[frame]; + bitmap_from_u64(mask, reg_mask); + for_each_set_bit(i, mask, 32) { + reg = &func->regs[i]; +@@ -2932,12 +2936,17 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno, + + int mark_chain_precision(struct bpf_verifier_env *env, int regno) + { +- return __mark_chain_precision(env, regno, -1); ++ return __mark_chain_precision(env, env->cur_state->curframe, regno, -1); + } + +-static int mark_chain_precision_stack(struct bpf_verifier_env *env, int spi) ++static int mark_chain_precision_frame(struct bpf_verifier_env *env, int frame, int regno) + { +- return __mark_chain_precision(env, -1, spi); ++ return __mark_chain_precision(env, frame, regno, -1); ++} ++ ++static int mark_chain_precision_stack_frame(struct bpf_verifier_env *env, int frame, int spi) ++{ ++ return __mark_chain_precision(env, frame, -1, spi); + } + + static bool is_spillable_regtype(enum bpf_reg_type type) +@@ -3186,14 +3195,17 @@ static int check_stack_write_var_off(struct bpf_verifier_env *env, + stype = &state->stack[spi].slot_type[slot % BPF_REG_SIZE]; + mark_stack_slot_scratched(env, spi); + +- if (!env->allow_ptr_leaks +- && *stype != NOT_INIT +- && *stype != SCALAR_VALUE) { +- /* Reject the write if there's are spilled pointers in +- * range. If we didn't reject here, the ptr status +- * would be erased below (even though not all slots are +- * actually overwritten), possibly opening the door to +- * leaks. ++ if (!env->allow_ptr_leaks && *stype != STACK_MISC && *stype != STACK_ZERO) { ++ /* Reject the write if range we may write to has not ++ * been initialized beforehand. If we didn't reject ++ * here, the ptr status would be erased below (even ++ * though not all slots are actually overwritten), ++ * possibly opening the door to leaks. ++ * ++ * We do however catch STACK_INVALID case below, and ++ * only allow reading possibly uninitialized memory ++ * later for CAP_PERFMON, as the write may not happen to ++ * that slot. + */ + verbose(env, "spilled ptr in range of var-offset stack write; insn %d, ptr off: %d", + insn_idx, i); +@@ -5159,10 +5171,6 @@ static int check_stack_range_initialized( + goto mark; + } + +- if (is_spilled_reg(&state->stack[spi]) && +- base_type(state->stack[spi].spilled_ptr.type) == PTR_TO_BTF_ID) +- goto mark; +- + if (is_spilled_reg(&state->stack[spi]) && + (state->stack[spi].spilled_ptr.type == SCALAR_VALUE || + env->allow_ptr_leaks)) { +@@ -5193,6 +5201,11 @@ mark: + mark_reg_read(env, &state->stack[spi].spilled_ptr, + state->stack[spi].spilled_ptr.parent, + REG_LIVE_READ64); ++ /* We do not set REG_LIVE_WRITTEN for stack slot, as we can not ++ * be sure that whether stack slot is written to or not. Hence, ++ * we must still conservatively propagate reads upwards even if ++ * helper may write to the entire memory range. ++ */ + } + return update_stack_depth(env, state, min_off); + } +@@ -9211,6 +9224,11 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env, + return err; + return adjust_ptr_min_max_vals(env, insn, + dst_reg, src_reg); ++ } else if (dst_reg->precise) { ++ /* if dst_reg is precise, src_reg should be precise as well */ ++ err = mark_chain_precision(env, insn->src_reg); ++ if (err) ++ return err; + } + } else { + /* Pretend the src is a reg with a known value, since we only +@@ -11847,34 +11865,36 @@ static int propagate_precision(struct bpf_verifier_env *env, + { + struct bpf_reg_state *state_reg; + struct bpf_func_state *state; +- int i, err = 0; ++ int i, err = 0, fr; + +- state = old->frame[old->curframe]; +- state_reg = state->regs; +- for (i = 0; i < BPF_REG_FP; i++, state_reg++) { +- if (state_reg->type != SCALAR_VALUE || +- !state_reg->precise) +- continue; +- if (env->log.level & BPF_LOG_LEVEL2) +- verbose(env, "propagating r%d\n", i); +- err = mark_chain_precision(env, i); +- if (err < 0) +- return err; +- } ++ for (fr = old->curframe; fr >= 0; fr--) { ++ state = old->frame[fr]; ++ state_reg = state->regs; ++ for (i = 0; i < BPF_REG_FP; i++, state_reg++) { ++ if (state_reg->type != SCALAR_VALUE || ++ !state_reg->precise) ++ continue; ++ if (env->log.level & BPF_LOG_LEVEL2) ++ verbose(env, "frame %d: propagating r%d\n", i, fr); ++ err = mark_chain_precision_frame(env, fr, i); ++ if (err < 0) ++ return err; ++ } + +- for (i = 0; i < state->allocated_stack / BPF_REG_SIZE; i++) { +- if (!is_spilled_reg(&state->stack[i])) +- continue; +- state_reg = &state->stack[i].spilled_ptr; +- if (state_reg->type != SCALAR_VALUE || +- !state_reg->precise) +- continue; +- if (env->log.level & BPF_LOG_LEVEL2) +- verbose(env, "propagating fp%d\n", +- (-i - 1) * BPF_REG_SIZE); +- err = mark_chain_precision_stack(env, i); +- if (err < 0) +- return err; ++ for (i = 0; i < state->allocated_stack / BPF_REG_SIZE; i++) { ++ if (!is_spilled_reg(&state->stack[i])) ++ continue; ++ state_reg = &state->stack[i].spilled_ptr; ++ if (state_reg->type != SCALAR_VALUE || ++ !state_reg->precise) ++ continue; ++ if (env->log.level & BPF_LOG_LEVEL2) ++ verbose(env, "frame %d: propagating fp%d\n", ++ (-i - 1) * BPF_REG_SIZE, fr); ++ err = mark_chain_precision_stack_frame(env, fr, i); ++ if (err < 0) ++ return err; ++ } + } + return 0; + } +@@ -13386,6 +13406,10 @@ static int opt_subreg_zext_lo32_rnd_hi32(struct bpf_verifier_env *env, + if (!bpf_jit_needs_zext() && !is_cmpxchg_insn(&insn)) + continue; + ++ /* Zero-extension is done by the caller. */ ++ if (bpf_pseudo_kfunc_call(&insn)) ++ continue; ++ + if (WARN_ON(load_reg == -1)) { + verbose(env, "verifier bug. zext_dst is set, but no reg is defined\n"); + return -EFAULT; +diff --git a/kernel/cpu.c b/kernel/cpu.c +index bbad5e375d3ba..98a7a7b1471b7 100644 +--- a/kernel/cpu.c ++++ b/kernel/cpu.c +@@ -663,21 +663,51 @@ static bool cpuhp_next_state(bool bringup, + return true; + } + +-static int cpuhp_invoke_callback_range(bool bringup, +- unsigned int cpu, +- struct cpuhp_cpu_state *st, +- enum cpuhp_state target) ++static int __cpuhp_invoke_callback_range(bool bringup, ++ unsigned int cpu, ++ struct cpuhp_cpu_state *st, ++ enum cpuhp_state target, ++ bool nofail) + { + enum cpuhp_state state; +- int err = 0; ++ int ret = 0; + + while (cpuhp_next_state(bringup, &state, st, target)) { ++ int err; ++ + err = cpuhp_invoke_callback(cpu, state, bringup, NULL, NULL); +- if (err) ++ if (!err) ++ continue; ++ ++ if (nofail) { ++ pr_warn("CPU %u %s state %s (%d) failed (%d)\n", ++ cpu, bringup ? "UP" : "DOWN", ++ cpuhp_get_step(st->state)->name, ++ st->state, err); ++ ret = -1; ++ } else { ++ ret = err; + break; ++ } + } + +- return err; ++ return ret; ++} ++ ++static inline int cpuhp_invoke_callback_range(bool bringup, ++ unsigned int cpu, ++ struct cpuhp_cpu_state *st, ++ enum cpuhp_state target) ++{ ++ return __cpuhp_invoke_callback_range(bringup, cpu, st, target, false); ++} ++ ++static inline void cpuhp_invoke_callback_range_nofail(bool bringup, ++ unsigned int cpu, ++ struct cpuhp_cpu_state *st, ++ enum cpuhp_state target) ++{ ++ __cpuhp_invoke_callback_range(bringup, cpu, st, target, true); + } + + static inline bool can_rollback_cpu(struct cpuhp_cpu_state *st) +@@ -999,7 +1029,6 @@ static int take_cpu_down(void *_param) + struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state); + enum cpuhp_state target = max((int)st->target, CPUHP_AP_OFFLINE); + int err, cpu = smp_processor_id(); +- int ret; + + /* Ensure this CPU doesn't handle any more interrupts. */ + err = __cpu_disable(); +@@ -1012,13 +1041,10 @@ static int take_cpu_down(void *_param) + */ + WARN_ON(st->state != (CPUHP_TEARDOWN_CPU - 1)); + +- /* Invoke the former CPU_DYING callbacks */ +- ret = cpuhp_invoke_callback_range(false, cpu, st, target); +- + /* +- * DYING must not fail! ++ * Invoke the former CPU_DYING callbacks. DYING must not fail! + */ +- WARN_ON_ONCE(ret); ++ cpuhp_invoke_callback_range_nofail(false, cpu, st, target); + + /* Give up timekeeping duties */ + tick_handover_do_timer(); +@@ -1296,16 +1322,14 @@ void notify_cpu_starting(unsigned int cpu) + { + struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu); + enum cpuhp_state target = min((int)st->target, CPUHP_AP_ONLINE); +- int ret; + + rcu_cpu_starting(cpu); /* Enables RCU usage on this CPU. */ + cpumask_set_cpu(cpu, &cpus_booted_once_mask); +- ret = cpuhp_invoke_callback_range(true, cpu, st, target); + + /* + * STARTING must not fail! + */ +- WARN_ON_ONCE(ret); ++ cpuhp_invoke_callback_range_nofail(true, cpu, st, target); + } + + /* +@@ -2326,8 +2350,10 @@ static ssize_t target_store(struct device *dev, struct device_attribute *attr, + + if (st->state < target) + ret = cpu_up(dev->id, target); +- else ++ else if (st->state > target) + ret = cpu_down(dev->id, target); ++ else if (WARN_ON(st->target != target)) ++ st->target = target; + out: + unlock_device_hotplug(); + return ret ? ret : count; +diff --git a/kernel/events/core.c b/kernel/events/core.c +index 7f04f995c9754..732b392fc5c63 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -11193,13 +11193,15 @@ static int pmu_dev_alloc(struct pmu *pmu) + + pmu->dev->groups = pmu->attr_groups; + device_initialize(pmu->dev); +- ret = dev_set_name(pmu->dev, "%s", pmu->name); +- if (ret) +- goto free_dev; + + dev_set_drvdata(pmu->dev, pmu); + pmu->dev->bus = &pmu_bus; + pmu->dev->release = pmu_dev_release; ++ ++ ret = dev_set_name(pmu->dev, "%s", pmu->name); ++ if (ret) ++ goto free_dev; ++ + ret = device_add(pmu->dev); + if (ret) + goto free_dev; +diff --git a/kernel/fork.c b/kernel/fork.c +index 08969f5aa38d5..844dfdc8c639c 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -535,6 +535,9 @@ void put_task_stack(struct task_struct *tsk) + + void free_task(struct task_struct *tsk) + { ++#ifdef CONFIG_SECCOMP ++ WARN_ON_ONCE(tsk->seccomp.filter); ++#endif + release_user_cpus_ptr(tsk); + scs_release(tsk); + +@@ -2406,12 +2409,6 @@ static __latent_entropy struct task_struct *copy_process( + + spin_lock(¤t->sighand->siglock); + +- /* +- * Copy seccomp details explicitly here, in case they were changed +- * before holding sighand lock. +- */ +- copy_seccomp(p); +- + rv_task_fork(p); + + rseq_fork(p, clone_flags); +@@ -2428,6 +2425,14 @@ static __latent_entropy struct task_struct *copy_process( + goto bad_fork_cancel_cgroup; + } + ++ /* No more failure paths after this point. */ ++ ++ /* ++ * Copy seccomp details explicitly here, in case they were changed ++ * before holding sighand lock. ++ */ ++ copy_seccomp(p); ++ + init_task_pid_links(p); + if (likely(p->pid)) { + ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace); +diff --git a/kernel/futex/core.c b/kernel/futex/core.c +index b22ef1efe7511..514e4582b8634 100644 +--- a/kernel/futex/core.c ++++ b/kernel/futex/core.c +@@ -638,6 +638,7 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + bool pi, bool pending_op) + { + u32 uval, nval, mval; ++ pid_t owner; + int err; + + /* Futex address must be 32bit aligned */ +@@ -659,6 +660,10 @@ retry: + * 2. A woken up waiter is killed before it can acquire the + * futex in user space. + * ++ * In the second case, the wake up notification could be generated ++ * by the unlock path in user space after setting the futex value ++ * to zero or by the kernel after setting the OWNER_DIED bit below. ++ * + * In both cases the TID validation below prevents a wakeup of + * potential waiters which can cause these waiters to block + * forever. +@@ -667,24 +672,27 @@ retry: + * + * 1) task->robust_list->list_op_pending != NULL + * @pending_op == true +- * 2) User space futex value == 0 ++ * 2) The owner part of user space futex value == 0 + * 3) Regular futex: @pi == false + * + * If these conditions are met, it is safe to attempt waking up a + * potential waiter without touching the user space futex value and +- * trying to set the OWNER_DIED bit. The user space futex value is +- * uncontended and the rest of the user space mutex state is +- * consistent, so a woken waiter will just take over the +- * uncontended futex. Setting the OWNER_DIED bit would create +- * inconsistent state and malfunction of the user space owner died +- * handling. ++ * trying to set the OWNER_DIED bit. If the futex value is zero, ++ * the rest of the user space mutex state is consistent, so a woken ++ * waiter will just take over the uncontended futex. Setting the ++ * OWNER_DIED bit would create inconsistent state and malfunction ++ * of the user space owner died handling. Otherwise, the OWNER_DIED ++ * bit is already set, and the woken waiter is expected to deal with ++ * this. + */ +- if (pending_op && !pi && !uval) { ++ owner = uval & FUTEX_TID_MASK; ++ ++ if (pending_op && !pi && !owner) { + futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY); + return 0; + } + +- if ((uval & FUTEX_TID_MASK) != task_pid_vnr(curr)) ++ if (owner != task_pid_vnr(curr)) + return 0; + + /* +diff --git a/kernel/futex/syscalls.c b/kernel/futex/syscalls.c +index 086a22d1adb78..a8074079b09e8 100644 +--- a/kernel/futex/syscalls.c ++++ b/kernel/futex/syscalls.c +@@ -286,19 +286,22 @@ SYSCALL_DEFINE5(futex_waitv, struct futex_waitv __user *, waiters, + } + + futexv = kcalloc(nr_futexes, sizeof(*futexv), GFP_KERNEL); +- if (!futexv) +- return -ENOMEM; ++ if (!futexv) { ++ ret = -ENOMEM; ++ goto destroy_timer; ++ } + + ret = futex_parse_waitv(futexv, waiters, nr_futexes); + if (!ret) + ret = futex_wait_multiple(futexv, nr_futexes, timeout ? &to : NULL); + ++ kfree(futexv); ++ ++destroy_timer: + if (timeout) { + hrtimer_cancel(&to.timer); + destroy_hrtimer_on_stack(&to.timer); + } +- +- kfree(futexv); + return ret; + } + +diff --git a/kernel/gcov/gcc_4_7.c b/kernel/gcov/gcc_4_7.c +index 7971e989e425b..74a4ef1da9ad7 100644 +--- a/kernel/gcov/gcc_4_7.c ++++ b/kernel/gcov/gcc_4_7.c +@@ -82,6 +82,7 @@ struct gcov_fn_info { + * @version: gcov version magic indicating the gcc version used for compilation + * @next: list head for a singly-linked list + * @stamp: uniquifying time stamp ++ * @checksum: unique object checksum + * @filename: name of the associated gcov data file + * @merge: merge functions (null for unused counter type) + * @n_functions: number of instrumented functions +@@ -94,6 +95,10 @@ struct gcov_info { + unsigned int version; + struct gcov_info *next; + unsigned int stamp; ++ /* Since GCC 12.1 a checksum field is added. */ ++#if (__GNUC__ >= 12) ++ unsigned int checksum; ++#endif + const char *filename; + void (*merge[GCOV_COUNTERS])(gcov_type *, unsigned int); + unsigned int n_functions; +diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h +index f09c60393e559..5fdc0b5575797 100644 +--- a/kernel/irq/internals.h ++++ b/kernel/irq/internals.h +@@ -52,6 +52,7 @@ enum { + * IRQS_PENDING - irq is pending and replayed later + * IRQS_SUSPENDED - irq is suspended + * IRQS_NMI - irq line is used to deliver NMIs ++ * IRQS_SYSFS - descriptor has been added to sysfs + */ + enum { + IRQS_AUTODETECT = 0x00000001, +@@ -64,6 +65,7 @@ enum { + IRQS_SUSPENDED = 0x00000800, + IRQS_TIMINGS = 0x00001000, + IRQS_NMI = 0x00002000, ++ IRQS_SYSFS = 0x00004000, + }; + + #include "debug.h" +diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c +index a91f9001103ce..fd09962744014 100644 +--- a/kernel/irq/irqdesc.c ++++ b/kernel/irq/irqdesc.c +@@ -288,22 +288,25 @@ static void irq_sysfs_add(int irq, struct irq_desc *desc) + if (irq_kobj_base) { + /* + * Continue even in case of failure as this is nothing +- * crucial. ++ * crucial and failures in the late irq_sysfs_init() ++ * cannot be rolled back. + */ + if (kobject_add(&desc->kobj, irq_kobj_base, "%d", irq)) + pr_warn("Failed to add kobject for irq %d\n", irq); ++ else ++ desc->istate |= IRQS_SYSFS; + } + } + + static void irq_sysfs_del(struct irq_desc *desc) + { + /* +- * If irq_sysfs_init() has not yet been invoked (early boot), then +- * irq_kobj_base is NULL and the descriptor was never added. +- * kobject_del() complains about a object with no parent, so make +- * it conditional. ++ * Only invoke kobject_del() when kobject_add() was successfully ++ * invoked for the descriptor. This covers both early boot, where ++ * sysfs is not initialized yet, and the case of a failed ++ * kobject_add() invocation. + */ +- if (irq_kobj_base) ++ if (desc->istate & IRQS_SYSFS) + kobject_del(&desc->kobj); + } + +diff --git a/kernel/kcsan/core.c b/kernel/kcsan/core.c +index fe12dfe254ecf..54d077e1a2dc7 100644 +--- a/kernel/kcsan/core.c ++++ b/kernel/kcsan/core.c +@@ -14,10 +14,12 @@ + #include <linux/init.h> + #include <linux/kernel.h> + #include <linux/list.h> ++#include <linux/minmax.h> + #include <linux/moduleparam.h> + #include <linux/percpu.h> + #include <linux/preempt.h> + #include <linux/sched.h> ++#include <linux/string.h> + #include <linux/uaccess.h> + + #include "encoding.h" +@@ -1308,3 +1310,51 @@ noinline void __tsan_atomic_signal_fence(int memorder) + } + } + EXPORT_SYMBOL(__tsan_atomic_signal_fence); ++ ++#ifdef __HAVE_ARCH_MEMSET ++void *__tsan_memset(void *s, int c, size_t count); ++noinline void *__tsan_memset(void *s, int c, size_t count) ++{ ++ /* ++ * Instead of not setting up watchpoints where accessed size is greater ++ * than MAX_ENCODABLE_SIZE, truncate checked size to MAX_ENCODABLE_SIZE. ++ */ ++ size_t check_len = min_t(size_t, count, MAX_ENCODABLE_SIZE); ++ ++ check_access(s, check_len, KCSAN_ACCESS_WRITE, _RET_IP_); ++ return memset(s, c, count); ++} ++#else ++void *__tsan_memset(void *s, int c, size_t count) __alias(memset); ++#endif ++EXPORT_SYMBOL(__tsan_memset); ++ ++#ifdef __HAVE_ARCH_MEMMOVE ++void *__tsan_memmove(void *dst, const void *src, size_t len); ++noinline void *__tsan_memmove(void *dst, const void *src, size_t len) ++{ ++ size_t check_len = min_t(size_t, len, MAX_ENCODABLE_SIZE); ++ ++ check_access(dst, check_len, KCSAN_ACCESS_WRITE, _RET_IP_); ++ check_access(src, check_len, 0, _RET_IP_); ++ return memmove(dst, src, len); ++} ++#else ++void *__tsan_memmove(void *dst, const void *src, size_t len) __alias(memmove); ++#endif ++EXPORT_SYMBOL(__tsan_memmove); ++ ++#ifdef __HAVE_ARCH_MEMCPY ++void *__tsan_memcpy(void *dst, const void *src, size_t len); ++noinline void *__tsan_memcpy(void *dst, const void *src, size_t len) ++{ ++ size_t check_len = min_t(size_t, len, MAX_ENCODABLE_SIZE); ++ ++ check_access(dst, check_len, KCSAN_ACCESS_WRITE, _RET_IP_); ++ check_access(src, check_len, 0, _RET_IP_); ++ return memcpy(dst, src, len); ++} ++#else ++void *__tsan_memcpy(void *dst, const void *src, size_t len) __alias(memcpy); ++#endif ++EXPORT_SYMBOL(__tsan_memcpy); +diff --git a/kernel/kprobes.c b/kernel/kprobes.c +index 3050631e528d9..1c18ecf9f98b1 100644 +--- a/kernel/kprobes.c ++++ b/kernel/kprobes.c +@@ -2213,13 +2213,9 @@ int register_kretprobe(struct kretprobe *rp) + rp->kp.post_handler = NULL; + + /* Pre-allocate memory for max kretprobe instances */ +- if (rp->maxactive <= 0) { +-#ifdef CONFIG_PREEMPTION ++ if (rp->maxactive <= 0) + rp->maxactive = max_t(unsigned int, 10, 2*num_possible_cpus()); +-#else +- rp->maxactive = num_possible_cpus(); +-#endif +- } ++ + #ifdef CONFIG_KRETPROBE_ON_RETHOOK + rp->rh = rethook_alloc((void *)rp, kretprobe_rethook_handler); + if (!rp->rh) +@@ -2364,6 +2360,14 @@ static void kill_kprobe(struct kprobe *p) + + lockdep_assert_held(&kprobe_mutex); + ++ /* ++ * The module is going away. We should disarm the kprobe which ++ * is using ftrace, because ftrace framework is still available at ++ * 'MODULE_STATE_GOING' notification. ++ */ ++ if (kprobe_ftrace(p) && !kprobe_disabled(p) && !kprobes_all_disarmed) ++ disarm_kprobe_ftrace(p); ++ + p->flags |= KPROBE_FLAG_GONE; + if (kprobe_aggrprobe(p)) { + /* +@@ -2380,14 +2384,6 @@ static void kill_kprobe(struct kprobe *p) + * the original probed function (which will be freed soon) any more. + */ + arch_remove_kprobe(p); +- +- /* +- * The module is going away. We should disarm the kprobe which +- * is using ftrace, because ftrace framework is still available at +- * 'MODULE_STATE_GOING' notification. +- */ +- if (kprobe_ftrace(p) && !kprobe_disabled(p) && !kprobes_all_disarmed) +- disarm_kprobe_ftrace(p); + } + + /* Disable one kprobe */ +diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c +index 7779ee8abc2a0..010cf4e6d0b8f 100644 +--- a/kernel/locking/rtmutex.c ++++ b/kernel/locking/rtmutex.c +@@ -89,15 +89,31 @@ static inline int __ww_mutex_check_kill(struct rt_mutex *lock, + * set this bit before looking at the lock. + */ + +-static __always_inline void +-rt_mutex_set_owner(struct rt_mutex_base *lock, struct task_struct *owner) ++static __always_inline struct task_struct * ++rt_mutex_owner_encode(struct rt_mutex_base *lock, struct task_struct *owner) + { + unsigned long val = (unsigned long)owner; + + if (rt_mutex_has_waiters(lock)) + val |= RT_MUTEX_HAS_WAITERS; + +- WRITE_ONCE(lock->owner, (struct task_struct *)val); ++ return (struct task_struct *)val; ++} ++ ++static __always_inline void ++rt_mutex_set_owner(struct rt_mutex_base *lock, struct task_struct *owner) ++{ ++ /* ++ * lock->wait_lock is held but explicit acquire semantics are needed ++ * for a new lock owner so WRITE_ONCE is insufficient. ++ */ ++ xchg_acquire(&lock->owner, rt_mutex_owner_encode(lock, owner)); ++} ++ ++static __always_inline void rt_mutex_clear_owner(struct rt_mutex_base *lock) ++{ ++ /* lock->wait_lock is held so the unlock provides release semantics. */ ++ WRITE_ONCE(lock->owner, rt_mutex_owner_encode(lock, NULL)); + } + + static __always_inline void clear_rt_mutex_waiters(struct rt_mutex_base *lock) +@@ -106,7 +122,8 @@ static __always_inline void clear_rt_mutex_waiters(struct rt_mutex_base *lock) + ((unsigned long)lock->owner & ~RT_MUTEX_HAS_WAITERS); + } + +-static __always_inline void fixup_rt_mutex_waiters(struct rt_mutex_base *lock) ++static __always_inline void ++fixup_rt_mutex_waiters(struct rt_mutex_base *lock, bool acquire_lock) + { + unsigned long owner, *p = (unsigned long *) &lock->owner; + +@@ -172,8 +189,21 @@ static __always_inline void fixup_rt_mutex_waiters(struct rt_mutex_base *lock) + * still set. + */ + owner = READ_ONCE(*p); +- if (owner & RT_MUTEX_HAS_WAITERS) +- WRITE_ONCE(*p, owner & ~RT_MUTEX_HAS_WAITERS); ++ if (owner & RT_MUTEX_HAS_WAITERS) { ++ /* ++ * See rt_mutex_set_owner() and rt_mutex_clear_owner() on ++ * why xchg_acquire() is used for updating owner for ++ * locking and WRITE_ONCE() for unlocking. ++ * ++ * WRITE_ONCE() would work for the acquire case too, but ++ * in case that the lock acquisition failed it might ++ * force other lockers into the slow path unnecessarily. ++ */ ++ if (acquire_lock) ++ xchg_acquire(p, owner & ~RT_MUTEX_HAS_WAITERS); ++ else ++ WRITE_ONCE(*p, owner & ~RT_MUTEX_HAS_WAITERS); ++ } + } + + /* +@@ -208,6 +238,13 @@ static __always_inline void mark_rt_mutex_waiters(struct rt_mutex_base *lock) + owner = *p; + } while (cmpxchg_relaxed(p, owner, + owner | RT_MUTEX_HAS_WAITERS) != owner); ++ ++ /* ++ * The cmpxchg loop above is relaxed to avoid back-to-back ACQUIRE ++ * operations in the event of contention. Ensure the successful ++ * cmpxchg is visible. ++ */ ++ smp_mb__after_atomic(); + } + + /* +@@ -1243,7 +1280,7 @@ static int __sched __rt_mutex_slowtrylock(struct rt_mutex_base *lock) + * try_to_take_rt_mutex() sets the lock waiters bit + * unconditionally. Clean this up. + */ +- fixup_rt_mutex_waiters(lock); ++ fixup_rt_mutex_waiters(lock, true); + + return ret; + } +@@ -1604,7 +1641,7 @@ static int __sched __rt_mutex_slowlock(struct rt_mutex_base *lock, + * try_to_take_rt_mutex() sets the waiter bit + * unconditionally. We might have to fix that up. + */ +- fixup_rt_mutex_waiters(lock); ++ fixup_rt_mutex_waiters(lock, true); + + trace_contention_end(lock, ret); + +@@ -1719,7 +1756,7 @@ static void __sched rtlock_slowlock_locked(struct rt_mutex_base *lock) + * try_to_take_rt_mutex() sets the waiter bit unconditionally. + * We might have to fix that up: + */ +- fixup_rt_mutex_waiters(lock); ++ fixup_rt_mutex_waiters(lock, true); + debug_rt_mutex_free_waiter(&waiter); + + trace_contention_end(lock, 0); +diff --git a/kernel/locking/rtmutex_api.c b/kernel/locking/rtmutex_api.c +index 900220941caac..cb9fdff76a8a3 100644 +--- a/kernel/locking/rtmutex_api.c ++++ b/kernel/locking/rtmutex_api.c +@@ -267,7 +267,7 @@ void __sched rt_mutex_init_proxy_locked(struct rt_mutex_base *lock, + void __sched rt_mutex_proxy_unlock(struct rt_mutex_base *lock) + { + debug_rt_mutex_proxy_unlock(lock); +- rt_mutex_set_owner(lock, NULL); ++ rt_mutex_clear_owner(lock); + } + + /** +@@ -382,7 +382,7 @@ int __sched rt_mutex_wait_proxy_lock(struct rt_mutex_base *lock, + * try_to_take_rt_mutex() sets the waiter bit unconditionally. We might + * have to fix that up. + */ +- fixup_rt_mutex_waiters(lock); ++ fixup_rt_mutex_waiters(lock, true); + raw_spin_unlock_irq(&lock->wait_lock); + + return ret; +@@ -438,7 +438,7 @@ bool __sched rt_mutex_cleanup_proxy_lock(struct rt_mutex_base *lock, + * try_to_take_rt_mutex() sets the waiter bit unconditionally. We might + * have to fix that up. + */ +- fixup_rt_mutex_waiters(lock); ++ fixup_rt_mutex_waiters(lock, false); + + raw_spin_unlock_irq(&lock->wait_lock); + +diff --git a/kernel/module/decompress.c b/kernel/module/decompress.c +index c033572d83f0e..720e719253cd1 100644 +--- a/kernel/module/decompress.c ++++ b/kernel/module/decompress.c +@@ -114,8 +114,8 @@ static ssize_t module_gzip_decompress(struct load_info *info, + do { + struct page *page = module_get_next_page(info); + +- if (!page) { +- retval = -ENOMEM; ++ if (IS_ERR(page)) { ++ retval = PTR_ERR(page); + goto out_inflate_end; + } + +@@ -173,8 +173,8 @@ static ssize_t module_xz_decompress(struct load_info *info, + do { + struct page *page = module_get_next_page(info); + +- if (!page) { +- retval = -ENOMEM; ++ if (IS_ERR(page)) { ++ retval = PTR_ERR(page); + goto out; + } + +diff --git a/kernel/padata.c b/kernel/padata.c +index e5819bb8bd1dc..de90af5fcbe6b 100644 +--- a/kernel/padata.c ++++ b/kernel/padata.c +@@ -207,14 +207,16 @@ int padata_do_parallel(struct padata_shell *ps, + pw = padata_work_alloc(); + spin_unlock(&padata_works_lock); + ++ if (!pw) { ++ /* Maximum works limit exceeded, run in the current task. */ ++ padata->parallel(padata); ++ } ++ + rcu_read_unlock_bh(); + + if (pw) { + padata_work_init(pw, padata_parallel_worker, padata, 0); + queue_work(pinst->parallel_wq, &pw->pw_work); +- } else { +- /* Maximum works limit exceeded, run in the current task. */ +- padata->parallel(padata); + } + + return 0; +@@ -388,13 +390,16 @@ void padata_do_serial(struct padata_priv *padata) + int hashed_cpu = padata_cpu_hash(pd, padata->seq_nr); + struct padata_list *reorder = per_cpu_ptr(pd->reorder_list, hashed_cpu); + struct padata_priv *cur; ++ struct list_head *pos; + + spin_lock(&reorder->lock); + /* Sort in ascending order of sequence number. */ +- list_for_each_entry_reverse(cur, &reorder->list, list) ++ list_for_each_prev(pos, &reorder->list) { ++ cur = list_entry(pos, struct padata_priv, list); + if (cur->seq_nr < padata->seq_nr) + break; +- list_add(&padata->list, &cur->list); ++ } ++ list_add(&padata->list, pos); + spin_unlock(&reorder->lock); + + /* +diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c +index 2a406753af904..c20ca5fb9adc8 100644 +--- a/kernel/power/snapshot.c ++++ b/kernel/power/snapshot.c +@@ -1723,8 +1723,8 @@ static unsigned long minimum_image_size(unsigned long saveable) + * /sys/power/reserved_size, respectively). To make this happen, we compute the + * total number of available page frames and allocate at least + * +- * ([page frames total] + PAGES_FOR_IO + [metadata pages]) / 2 +- * + 2 * DIV_ROUND_UP(reserved_size, PAGE_SIZE) ++ * ([page frames total] - PAGES_FOR_IO - [metadata pages]) / 2 ++ * - 2 * DIV_ROUND_UP(reserved_size, PAGE_SIZE) + * + * of them, which corresponds to the maximum size of a hibernation image. + * +diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c +index 93416afebd59c..14d9384fba056 100644 +--- a/kernel/rcu/tree.c ++++ b/kernel/rcu/tree.c +@@ -2418,7 +2418,7 @@ void rcu_force_quiescent_state(void) + struct rcu_node *rnp_old = NULL; + + /* Funnel through hierarchy to reduce memory contention. */ +- rnp = __this_cpu_read(rcu_data.mynode); ++ rnp = raw_cpu_read(rcu_data.mynode); + for (; rnp != NULL; rnp = rnp->parent) { + ret = (READ_ONCE(rcu_state.gp_flags) & RCU_GP_FLAG_FQS) || + !raw_spin_trylock(&rnp->fqslock); +diff --git a/kernel/relay.c b/kernel/relay.c +index d7edc934c56d5..88bcb09f0a1f2 100644 +--- a/kernel/relay.c ++++ b/kernel/relay.c +@@ -148,13 +148,13 @@ static struct rchan_buf *relay_create_buf(struct rchan *chan) + { + struct rchan_buf *buf; + +- if (chan->n_subbufs > KMALLOC_MAX_SIZE / sizeof(size_t *)) ++ if (chan->n_subbufs > KMALLOC_MAX_SIZE / sizeof(size_t)) + return NULL; + + buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL); + if (!buf) + return NULL; +- buf->padding = kmalloc_array(chan->n_subbufs, sizeof(size_t *), ++ buf->padding = kmalloc_array(chan->n_subbufs, sizeof(size_t), + GFP_KERNEL); + if (!buf->padding) + goto free_buf; +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index daff72f003858..535af9fbea7b8 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -1392,7 +1392,7 @@ static inline void uclamp_idle_reset(struct rq *rq, enum uclamp_id clamp_id, + if (!(rq->uclamp_flags & UCLAMP_FLAG_IDLE)) + return; + +- WRITE_ONCE(rq->uclamp[clamp_id].value, clamp_value); ++ uclamp_rq_set(rq, clamp_id, clamp_value); + } + + static inline +@@ -1543,8 +1543,8 @@ static inline void uclamp_rq_inc_id(struct rq *rq, struct task_struct *p, + if (bucket->tasks == 1 || uc_se->value > bucket->value) + bucket->value = uc_se->value; + +- if (uc_se->value > READ_ONCE(uc_rq->value)) +- WRITE_ONCE(uc_rq->value, uc_se->value); ++ if (uc_se->value > uclamp_rq_get(rq, clamp_id)) ++ uclamp_rq_set(rq, clamp_id, uc_se->value); + } + + /* +@@ -1610,7 +1610,7 @@ static inline void uclamp_rq_dec_id(struct rq *rq, struct task_struct *p, + if (likely(bucket->tasks)) + return; + +- rq_clamp = READ_ONCE(uc_rq->value); ++ rq_clamp = uclamp_rq_get(rq, clamp_id); + /* + * Defensive programming: this should never happen. If it happens, + * e.g. due to future modification, warn and fixup the expected value. +@@ -1618,7 +1618,7 @@ static inline void uclamp_rq_dec_id(struct rq *rq, struct task_struct *p, + SCHED_WARN_ON(bucket->value > rq_clamp); + if (bucket->value >= rq_clamp) { + bkt_clamp = uclamp_rq_max_value(rq, clamp_id, uc_se->value); +- WRITE_ONCE(uc_rq->value, bkt_clamp); ++ uclamp_rq_set(rq, clamp_id, bkt_clamp); + } + } + +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index e4a0b8bd941c7..0f32acb05055f 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -4280,14 +4280,16 @@ static inline unsigned long task_util_est(struct task_struct *p) + } + + #ifdef CONFIG_UCLAMP_TASK +-static inline unsigned long uclamp_task_util(struct task_struct *p) ++static inline unsigned long uclamp_task_util(struct task_struct *p, ++ unsigned long uclamp_min, ++ unsigned long uclamp_max) + { +- return clamp(task_util_est(p), +- uclamp_eff_value(p, UCLAMP_MIN), +- uclamp_eff_value(p, UCLAMP_MAX)); ++ return clamp(task_util_est(p), uclamp_min, uclamp_max); + } + #else +-static inline unsigned long uclamp_task_util(struct task_struct *p) ++static inline unsigned long uclamp_task_util(struct task_struct *p, ++ unsigned long uclamp_min, ++ unsigned long uclamp_max) + { + return task_util_est(p); + } +@@ -4426,10 +4428,135 @@ done: + trace_sched_util_est_se_tp(&p->se); + } + +-static inline int task_fits_capacity(struct task_struct *p, +- unsigned long capacity) ++static inline int util_fits_cpu(unsigned long util, ++ unsigned long uclamp_min, ++ unsigned long uclamp_max, ++ int cpu) + { +- return fits_capacity(uclamp_task_util(p), capacity); ++ unsigned long capacity_orig, capacity_orig_thermal; ++ unsigned long capacity = capacity_of(cpu); ++ bool fits, uclamp_max_fits; ++ ++ /* ++ * Check if the real util fits without any uclamp boost/cap applied. ++ */ ++ fits = fits_capacity(util, capacity); ++ ++ if (!uclamp_is_used()) ++ return fits; ++ ++ /* ++ * We must use capacity_orig_of() for comparing against uclamp_min and ++ * uclamp_max. We only care about capacity pressure (by using ++ * capacity_of()) for comparing against the real util. ++ * ++ * If a task is boosted to 1024 for example, we don't want a tiny ++ * pressure to skew the check whether it fits a CPU or not. ++ * ++ * Similarly if a task is capped to capacity_orig_of(little_cpu), it ++ * should fit a little cpu even if there's some pressure. ++ * ++ * Only exception is for thermal pressure since it has a direct impact ++ * on available OPP of the system. ++ * ++ * We honour it for uclamp_min only as a drop in performance level ++ * could result in not getting the requested minimum performance level. ++ * ++ * For uclamp_max, we can tolerate a drop in performance level as the ++ * goal is to cap the task. So it's okay if it's getting less. ++ * ++ * In case of capacity inversion, which is not handled yet, we should ++ * honour the inverted capacity for both uclamp_min and uclamp_max all ++ * the time. ++ */ ++ capacity_orig = capacity_orig_of(cpu); ++ capacity_orig_thermal = capacity_orig - arch_scale_thermal_pressure(cpu); ++ ++ /* ++ * We want to force a task to fit a cpu as implied by uclamp_max. ++ * But we do have some corner cases to cater for.. ++ * ++ * ++ * C=z ++ * | ___ ++ * | C=y | | ++ * |_ _ _ _ _ _ _ _ _ ___ _ _ _ | _ | _ _ _ _ _ uclamp_max ++ * | C=x | | | | ++ * | ___ | | | | ++ * | | | | | | | (util somewhere in this region) ++ * | | | | | | | ++ * | | | | | | | ++ * +---------------------------------------- ++ * cpu0 cpu1 cpu2 ++ * ++ * In the above example if a task is capped to a specific performance ++ * point, y, then when: ++ * ++ * * util = 80% of x then it does not fit on cpu0 and should migrate ++ * to cpu1 ++ * * util = 80% of y then it is forced to fit on cpu1 to honour ++ * uclamp_max request. ++ * ++ * which is what we're enforcing here. A task always fits if ++ * uclamp_max <= capacity_orig. But when uclamp_max > capacity_orig, ++ * the normal upmigration rules should withhold still. ++ * ++ * Only exception is when we are on max capacity, then we need to be ++ * careful not to block overutilized state. This is so because: ++ * ++ * 1. There's no concept of capping at max_capacity! We can't go ++ * beyond this performance level anyway. ++ * 2. The system is being saturated when we're operating near ++ * max capacity, it doesn't make sense to block overutilized. ++ */ ++ uclamp_max_fits = (capacity_orig == SCHED_CAPACITY_SCALE) && (uclamp_max == SCHED_CAPACITY_SCALE); ++ uclamp_max_fits = !uclamp_max_fits && (uclamp_max <= capacity_orig); ++ fits = fits || uclamp_max_fits; ++ ++ /* ++ * ++ * C=z ++ * | ___ (region a, capped, util >= uclamp_max) ++ * | C=y | | ++ * |_ _ _ _ _ _ _ _ _ ___ _ _ _ | _ | _ _ _ _ _ uclamp_max ++ * | C=x | | | | ++ * | ___ | | | | (region b, uclamp_min <= util <= uclamp_max) ++ * |_ _ _|_ _|_ _ _ _| _ | _ _ _| _ | _ _ _ _ _ uclamp_min ++ * | | | | | | | ++ * | | | | | | | (region c, boosted, util < uclamp_min) ++ * +---------------------------------------- ++ * cpu0 cpu1 cpu2 ++ * ++ * a) If util > uclamp_max, then we're capped, we don't care about ++ * actual fitness value here. We only care if uclamp_max fits ++ * capacity without taking margin/pressure into account. ++ * See comment above. ++ * ++ * b) If uclamp_min <= util <= uclamp_max, then the normal ++ * fits_capacity() rules apply. Except we need to ensure that we ++ * enforce we remain within uclamp_max, see comment above. ++ * ++ * c) If util < uclamp_min, then we are boosted. Same as (b) but we ++ * need to take into account the boosted value fits the CPU without ++ * taking margin/pressure into account. ++ * ++ * Cases (a) and (b) are handled in the 'fits' variable already. We ++ * just need to consider an extra check for case (c) after ensuring we ++ * handle the case uclamp_min > uclamp_max. ++ */ ++ uclamp_min = min(uclamp_min, uclamp_max); ++ if (util < uclamp_min && capacity_orig != SCHED_CAPACITY_SCALE) ++ fits = fits && (uclamp_min <= capacity_orig_thermal); ++ ++ return fits; ++} ++ ++static inline int task_fits_cpu(struct task_struct *p, int cpu) ++{ ++ unsigned long uclamp_min = uclamp_eff_value(p, UCLAMP_MIN); ++ unsigned long uclamp_max = uclamp_eff_value(p, UCLAMP_MAX); ++ unsigned long util = task_util_est(p); ++ return util_fits_cpu(util, uclamp_min, uclamp_max, cpu); + } + + static inline void update_misfit_status(struct task_struct *p, struct rq *rq) +@@ -4442,7 +4569,7 @@ static inline void update_misfit_status(struct task_struct *p, struct rq *rq) + return; + } + +- if (task_fits_capacity(p, capacity_of(cpu_of(rq)))) { ++ if (task_fits_cpu(p, cpu_of(rq))) { + rq->misfit_task_load = 0; + return; + } +@@ -5862,7 +5989,10 @@ static inline void hrtick_update(struct rq *rq) + #ifdef CONFIG_SMP + static inline bool cpu_overutilized(int cpu) + { +- return !fits_capacity(cpu_util_cfs(cpu), capacity_of(cpu)); ++ unsigned long rq_util_min = uclamp_rq_get(cpu_rq(cpu), UCLAMP_MIN); ++ unsigned long rq_util_max = uclamp_rq_get(cpu_rq(cpu), UCLAMP_MAX); ++ ++ return !util_fits_cpu(cpu_util_cfs(cpu), rq_util_min, rq_util_max, cpu); + } + + static inline void update_overutilized_status(struct rq *rq) +@@ -6654,21 +6784,23 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, bool + static int + select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target) + { +- unsigned long task_util, best_cap = 0; ++ unsigned long task_util, util_min, util_max, best_cap = 0; + int cpu, best_cpu = -1; + struct cpumask *cpus; + + cpus = this_cpu_cpumask_var_ptr(select_rq_mask); + cpumask_and(cpus, sched_domain_span(sd), p->cpus_ptr); + +- task_util = uclamp_task_util(p); ++ task_util = task_util_est(p); ++ util_min = uclamp_eff_value(p, UCLAMP_MIN); ++ util_max = uclamp_eff_value(p, UCLAMP_MAX); + + for_each_cpu_wrap(cpu, cpus, target) { + unsigned long cpu_cap = capacity_of(cpu); + + if (!available_idle_cpu(cpu) && !sched_idle_cpu(cpu)) + continue; +- if (fits_capacity(task_util, cpu_cap)) ++ if (util_fits_cpu(task_util, util_min, util_max, cpu)) + return cpu; + + if (cpu_cap > best_cap) { +@@ -6680,10 +6812,13 @@ select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target) + return best_cpu; + } + +-static inline bool asym_fits_capacity(unsigned long task_util, int cpu) ++static inline bool asym_fits_cpu(unsigned long util, ++ unsigned long util_min, ++ unsigned long util_max, ++ int cpu) + { + if (sched_asym_cpucap_active()) +- return fits_capacity(task_util, capacity_of(cpu)); ++ return util_fits_cpu(util, util_min, util_max, cpu); + + return true; + } +@@ -6695,7 +6830,7 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) + { + bool has_idle_core = false; + struct sched_domain *sd; +- unsigned long task_util; ++ unsigned long task_util, util_min, util_max; + int i, recent_used_cpu; + + /* +@@ -6704,7 +6839,9 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) + */ + if (sched_asym_cpucap_active()) { + sync_entity_load_avg(&p->se); +- task_util = uclamp_task_util(p); ++ task_util = task_util_est(p); ++ util_min = uclamp_eff_value(p, UCLAMP_MIN); ++ util_max = uclamp_eff_value(p, UCLAMP_MAX); + } + + /* +@@ -6713,7 +6850,7 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) + lockdep_assert_irqs_disabled(); + + if ((available_idle_cpu(target) || sched_idle_cpu(target)) && +- asym_fits_capacity(task_util, target)) ++ asym_fits_cpu(task_util, util_min, util_max, target)) + return target; + + /* +@@ -6721,7 +6858,7 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) + */ + if (prev != target && cpus_share_cache(prev, target) && + (available_idle_cpu(prev) || sched_idle_cpu(prev)) && +- asym_fits_capacity(task_util, prev)) ++ asym_fits_cpu(task_util, util_min, util_max, prev)) + return prev; + + /* +@@ -6736,7 +6873,7 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) + in_task() && + prev == smp_processor_id() && + this_rq()->nr_running <= 1 && +- asym_fits_capacity(task_util, prev)) { ++ asym_fits_cpu(task_util, util_min, util_max, prev)) { + return prev; + } + +@@ -6748,7 +6885,7 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) + cpus_share_cache(recent_used_cpu, target) && + (available_idle_cpu(recent_used_cpu) || sched_idle_cpu(recent_used_cpu)) && + cpumask_test_cpu(p->recent_used_cpu, p->cpus_ptr) && +- asym_fits_capacity(task_util, recent_used_cpu)) { ++ asym_fits_cpu(task_util, util_min, util_max, recent_used_cpu)) { + return recent_used_cpu; + } + +@@ -7044,6 +7181,8 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu) + { + struct cpumask *cpus = this_cpu_cpumask_var_ptr(select_rq_mask); + unsigned long prev_delta = ULONG_MAX, best_delta = ULONG_MAX; ++ unsigned long p_util_min = uclamp_is_used() ? uclamp_eff_value(p, UCLAMP_MIN) : 0; ++ unsigned long p_util_max = uclamp_is_used() ? uclamp_eff_value(p, UCLAMP_MAX) : 1024; + struct root_domain *rd = this_rq()->rd; + int cpu, best_energy_cpu, target = -1; + struct sched_domain *sd; +@@ -7068,7 +7207,7 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu) + target = prev_cpu; + + sync_entity_load_avg(&p->se); +- if (!task_util_est(p)) ++ if (!uclamp_task_util(p, p_util_min, p_util_max)) + goto unlock; + + eenv_task_busy_time(&eenv, p, prev_cpu); +@@ -7076,6 +7215,8 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu) + for (; pd; pd = pd->next) { + unsigned long cpu_cap, cpu_thermal_cap, util; + unsigned long cur_delta, max_spare_cap = 0; ++ unsigned long rq_util_min, rq_util_max; ++ unsigned long util_min, util_max; + bool compute_prev_delta = false; + int max_spare_cap_cpu = -1; + unsigned long base_energy; +@@ -7112,8 +7253,26 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu) + * much capacity we can get out of the CPU; this is + * aligned with sched_cpu_util(). + */ +- util = uclamp_rq_util_with(cpu_rq(cpu), util, p); +- if (!fits_capacity(util, cpu_cap)) ++ if (uclamp_is_used()) { ++ if (uclamp_rq_is_idle(cpu_rq(cpu))) { ++ util_min = p_util_min; ++ util_max = p_util_max; ++ } else { ++ /* ++ * Open code uclamp_rq_util_with() except for ++ * the clamp() part. Ie: apply max aggregation ++ * only. util_fits_cpu() logic requires to ++ * operate on non clamped util but must use the ++ * max-aggregated uclamp_{min, max}. ++ */ ++ rq_util_min = uclamp_rq_get(cpu_rq(cpu), UCLAMP_MIN); ++ rq_util_max = uclamp_rq_get(cpu_rq(cpu), UCLAMP_MAX); ++ ++ util_min = max(rq_util_min, p_util_min); ++ util_max = max(rq_util_max, p_util_max); ++ } ++ } ++ if (!util_fits_cpu(util, util_min, util_max, cpu)) + continue; + + lsub_positive(&cpu_cap, util); +@@ -8276,7 +8435,7 @@ static int detach_tasks(struct lb_env *env) + + case migrate_misfit: + /* This is not a misfit task */ +- if (task_fits_capacity(p, capacity_of(env->src_cpu))) ++ if (task_fits_cpu(p, env->src_cpu)) + goto next; + + env->imbalance = 0; +@@ -9281,6 +9440,10 @@ static inline void update_sg_wakeup_stats(struct sched_domain *sd, + + memset(sgs, 0, sizeof(*sgs)); + ++ /* Assume that task can't fit any CPU of the group */ ++ if (sd->flags & SD_ASYM_CPUCAPACITY) ++ sgs->group_misfit_task_load = 1; ++ + for_each_cpu(i, sched_group_span(group)) { + struct rq *rq = cpu_rq(i); + unsigned int local; +@@ -9300,12 +9463,12 @@ static inline void update_sg_wakeup_stats(struct sched_domain *sd, + if (!nr_running && idle_cpu_without(i, p)) + sgs->idle_cpus++; + +- } ++ /* Check if task fits in the CPU */ ++ if (sd->flags & SD_ASYM_CPUCAPACITY && ++ sgs->group_misfit_task_load && ++ task_fits_cpu(p, i)) ++ sgs->group_misfit_task_load = 0; + +- /* Check if task fits in the group */ +- if (sd->flags & SD_ASYM_CPUCAPACITY && +- !task_fits_capacity(p, group->sgc->max_capacity)) { +- sgs->group_misfit_task_load = 1; + } + + sgs->group_capacity = group->sgc->capacity; +diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c +index ee2ecc081422e..7f40d87e8f509 100644 +--- a/kernel/sched/psi.c ++++ b/kernel/sched/psi.c +@@ -539,10 +539,12 @@ static u64 update_triggers(struct psi_group *group, u64 now) + + /* Calculate growth since last update */ + growth = window_update(&t->win, now, total[t->state]); +- if (growth < t->threshold) +- continue; ++ if (!t->pending_event) { ++ if (growth < t->threshold) ++ continue; + +- t->pending_event = true; ++ t->pending_event = true; ++ } + } + /* Limit event signaling to once per window */ + if (now < t->last_event_time + t->win.size) +diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h +index a4a20046e586e..d6d488e8eb554 100644 +--- a/kernel/sched/sched.h ++++ b/kernel/sched/sched.h +@@ -2979,6 +2979,23 @@ static inline unsigned long cpu_util_rt(struct rq *rq) + #ifdef CONFIG_UCLAMP_TASK + unsigned long uclamp_eff_value(struct task_struct *p, enum uclamp_id clamp_id); + ++static inline unsigned long uclamp_rq_get(struct rq *rq, ++ enum uclamp_id clamp_id) ++{ ++ return READ_ONCE(rq->uclamp[clamp_id].value); ++} ++ ++static inline void uclamp_rq_set(struct rq *rq, enum uclamp_id clamp_id, ++ unsigned int value) ++{ ++ WRITE_ONCE(rq->uclamp[clamp_id].value, value); ++} ++ ++static inline bool uclamp_rq_is_idle(struct rq *rq) ++{ ++ return rq->uclamp_flags & UCLAMP_FLAG_IDLE; ++} ++ + /** + * uclamp_rq_util_with - clamp @util with @rq and @p effective uclamp values. + * @rq: The rq to clamp against. Must not be NULL. +@@ -3014,12 +3031,12 @@ unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long util, + * Ignore last runnable task's max clamp, as this task will + * reset it. Similarly, no need to read the rq's min clamp. + */ +- if (rq->uclamp_flags & UCLAMP_FLAG_IDLE) ++ if (uclamp_rq_is_idle(rq)) + goto out; + } + +- min_util = max_t(unsigned long, min_util, READ_ONCE(rq->uclamp[UCLAMP_MIN].value)); +- max_util = max_t(unsigned long, max_util, READ_ONCE(rq->uclamp[UCLAMP_MAX].value)); ++ min_util = max_t(unsigned long, min_util, uclamp_rq_get(rq, UCLAMP_MIN)); ++ max_util = max_t(unsigned long, max_util, uclamp_rq_get(rq, UCLAMP_MAX)); + out: + /* + * Since CPU's {min,max}_util clamps are MAX aggregated considering +@@ -3060,6 +3077,15 @@ static inline bool uclamp_is_used(void) + return static_branch_likely(&sched_uclamp_used); + } + #else /* CONFIG_UCLAMP_TASK */ ++static inline unsigned long uclamp_eff_value(struct task_struct *p, ++ enum uclamp_id clamp_id) ++{ ++ if (clamp_id == UCLAMP_MIN) ++ return 0; ++ ++ return SCHED_CAPACITY_SCALE; ++} ++ + static inline + unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long util, + struct task_struct *p) +@@ -3073,6 +3099,25 @@ static inline bool uclamp_is_used(void) + { + return false; + } ++ ++static inline unsigned long uclamp_rq_get(struct rq *rq, ++ enum uclamp_id clamp_id) ++{ ++ if (clamp_id == UCLAMP_MIN) ++ return 0; ++ ++ return SCHED_CAPACITY_SCALE; ++} ++ ++static inline void uclamp_rq_set(struct rq *rq, enum uclamp_id clamp_id, ++ unsigned int value) ++{ ++} ++ ++static inline bool uclamp_rq_is_idle(struct rq *rq) ++{ ++ return false; ++} + #endif /* CONFIG_UCLAMP_TASK */ + + #ifdef CONFIG_HAVE_SCHED_AVG_IRQ +diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c +index a995ea1ef849a..a66cff5a18579 100644 +--- a/kernel/trace/blktrace.c ++++ b/kernel/trace/blktrace.c +@@ -1548,7 +1548,8 @@ blk_trace_event_print_binary(struct trace_iterator *iter, int flags, + + static enum print_line_t blk_tracer_print_line(struct trace_iterator *iter) + { +- if (!(blk_tracer_flags.val & TRACE_BLK_OPT_CLASSIC)) ++ if ((iter->ent->type != TRACE_BLK) || ++ !(blk_tracer_flags.val & TRACE_BLK_OPT_CLASSIC)) + return TRACE_TYPE_UNHANDLED; + + return print_one_line(iter, true); +diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c +index 1c82478e8dffe..b6e5724a9ea35 100644 +--- a/kernel/trace/trace_events_hist.c ++++ b/kernel/trace/trace_events_hist.c +@@ -6438,7 +6438,7 @@ enable: + if (se) + se->ref++; + out: +- if (ret == 0) ++ if (ret == 0 && glob[0]) + hist_err_clear(); + + return ret; +diff --git a/kernel/trace/trace_events_user.c b/kernel/trace/trace_events_user.c +index 539b08ae70207..9cb53182bb31c 100644 +--- a/kernel/trace/trace_events_user.c ++++ b/kernel/trace/trace_events_user.c +@@ -1359,6 +1359,7 @@ put_user_lock: + put_user: + user_event_destroy_fields(user); + user_event_destroy_validators(user); ++ kfree(user->call.print_fmt); + kfree(user); + return ret; + } +diff --git a/lib/debugobjects.c b/lib/debugobjects.c +index 337d797a71416..6f8e5dd1dcd0c 100644 +--- a/lib/debugobjects.c ++++ b/lib/debugobjects.c +@@ -437,6 +437,7 @@ static int object_cpu_offline(unsigned int cpu) + struct debug_percpu_free *percpu_pool; + struct hlist_node *tmp; + struct debug_obj *obj; ++ unsigned long flags; + + /* Remote access is safe as the CPU is dead already */ + percpu_pool = per_cpu_ptr(&percpu_obj_pool, cpu); +@@ -444,6 +445,12 @@ static int object_cpu_offline(unsigned int cpu) + hlist_del(&obj->node); + kmem_cache_free(obj_cache, obj); + } ++ ++ raw_spin_lock_irqsave(&pool_lock, flags); ++ obj_pool_used -= percpu_pool->obj_free; ++ debug_objects_freed += percpu_pool->obj_free; ++ raw_spin_unlock_irqrestore(&pool_lock, flags); ++ + percpu_pool->obj_free = 0; + + return 0; +@@ -1318,6 +1325,8 @@ static int __init debug_objects_replace_static_objects(void) + hlist_add_head(&obj->node, &objects); + } + ++ debug_objects_allocated += i; ++ + /* + * debug_objects_mem_init() is now called early that only one CPU is up + * and interrupts have been disabled, so it is safe to replace the +@@ -1386,6 +1395,7 @@ void __init debug_objects_mem_init(void) + debug_objects_enabled = 0; + kmem_cache_destroy(obj_cache); + pr_warn("out of memory.\n"); ++ return; + } else + debug_objects_selftest(); + +diff --git a/lib/fonts/fonts.c b/lib/fonts/fonts.c +index 5f4b07b56cd9c..9738664386088 100644 +--- a/lib/fonts/fonts.c ++++ b/lib/fonts/fonts.c +@@ -135,8 +135,8 @@ const struct font_desc *get_default_font(int xres, int yres, u32 font_w, + if (res > 20) + c += 20 - res; + +- if ((font_w & (1 << (f->width - 1))) && +- (font_h & (1 << (f->height - 1)))) ++ if ((font_w & (1U << (f->width - 1))) && ++ (font_h & (1U << (f->height - 1)))) + c += 1000; + + if (c > cc) { +diff --git a/lib/maple_tree.c b/lib/maple_tree.c +index df352f6ccc240..fe21bf276d91c 100644 +--- a/lib/maple_tree.c ++++ b/lib/maple_tree.c +@@ -2989,7 +2989,9 @@ static int mas_spanning_rebalance(struct ma_state *mas, + mast->free = &free; + mast->destroy = &destroy; + l_mas.node = r_mas.node = m_mas.node = MAS_NONE; +- if (!(mast->orig_l->min && mast->orig_r->max == ULONG_MAX) && ++ ++ /* Check if this is not root and has sufficient data. */ ++ if (((mast->orig_l->min != 0) || (mast->orig_r->max != ULONG_MAX)) && + unlikely(mast->bn->b_end <= mt_min_slots[mast->bn->type])) + mast_spanning_rebalance(mast); + +diff --git a/lib/notifier-error-inject.c b/lib/notifier-error-inject.c +index 21016b32d3131..2b24ea6c94979 100644 +--- a/lib/notifier-error-inject.c ++++ b/lib/notifier-error-inject.c +@@ -15,7 +15,7 @@ static int debugfs_errno_get(void *data, u64 *val) + return 0; + } + +-DEFINE_SIMPLE_ATTRIBUTE(fops_errno, debugfs_errno_get, debugfs_errno_set, ++DEFINE_SIMPLE_ATTRIBUTE_SIGNED(fops_errno, debugfs_errno_get, debugfs_errno_set, + "%lld\n"); + + static struct dentry *debugfs_create_errno(const char *name, umode_t mode, +diff --git a/lib/test_firmware.c b/lib/test_firmware.c +index c82b65947ce68..1c5a2adb16ef5 100644 +--- a/lib/test_firmware.c ++++ b/lib/test_firmware.c +@@ -1491,6 +1491,7 @@ static int __init test_firmware_init(void) + + rc = misc_register(&test_fw_misc_device); + if (rc) { ++ __test_firmware_config_free(); + kfree(test_fw_config); + pr_err("could not register misc device: %d\n", rc); + return rc; +diff --git a/lib/test_maple_tree.c b/lib/test_maple_tree.c +index f425f169ef089..497fc93ccf9ec 100644 +--- a/lib/test_maple_tree.c ++++ b/lib/test_maple_tree.c +@@ -2498,6 +2498,25 @@ static noinline void check_dup(struct maple_tree *mt) + } + } + ++static noinline void check_bnode_min_spanning(struct maple_tree *mt) ++{ ++ int i = 50; ++ MA_STATE(mas, mt, 0, 0); ++ ++ mt_set_non_kernel(9999); ++ mas_lock(&mas); ++ do { ++ mas_set_range(&mas, i*10, i*10+9); ++ mas_store(&mas, check_bnode_min_spanning); ++ } while (i--); ++ ++ mas_set_range(&mas, 240, 509); ++ mas_store(&mas, NULL); ++ mas_unlock(&mas); ++ mas_destroy(&mas); ++ mt_set_non_kernel(0); ++} ++ + static DEFINE_MTREE(tree); + static int maple_tree_seed(void) + { +@@ -2742,6 +2761,10 @@ static int maple_tree_seed(void) + check_dup(&tree); + mtree_destroy(&tree); + ++ mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE); ++ check_bnode_min_spanning(&tree); ++ mtree_destroy(&tree); ++ + #if defined(BENCH) + skip: + #endif +diff --git a/mm/compaction.c b/mm/compaction.c +index 1f6da31dd9a50..ca1603524bbe0 100644 +--- a/mm/compaction.c ++++ b/mm/compaction.c +@@ -1344,7 +1344,7 @@ move_freelist_tail(struct list_head *freelist, struct page *freepage) + } + + static void +-fast_isolate_around(struct compact_control *cc, unsigned long pfn, unsigned long nr_isolated) ++fast_isolate_around(struct compact_control *cc, unsigned long pfn) + { + unsigned long start_pfn, end_pfn; + struct page *page; +@@ -1365,21 +1365,13 @@ fast_isolate_around(struct compact_control *cc, unsigned long pfn, unsigned long + if (!page) + return; + +- /* Scan before */ +- if (start_pfn != pfn) { +- isolate_freepages_block(cc, &start_pfn, pfn, &cc->freepages, 1, false); +- if (cc->nr_freepages >= cc->nr_migratepages) +- return; +- } +- +- /* Scan after */ +- start_pfn = pfn + nr_isolated; +- if (start_pfn < end_pfn) +- isolate_freepages_block(cc, &start_pfn, end_pfn, &cc->freepages, 1, false); ++ isolate_freepages_block(cc, &start_pfn, end_pfn, &cc->freepages, 1, false); + + /* Skip this pageblock in the future as it's full or nearly full */ + if (cc->nr_freepages < cc->nr_migratepages) + set_pageblock_skip(page); ++ ++ return; + } + + /* Search orders in round-robin fashion */ +@@ -1556,7 +1548,7 @@ fast_isolate_freepages(struct compact_control *cc) + return cc->free_pfn; + + low_pfn = page_to_pfn(page); +- fast_isolate_around(cc, low_pfn, nr_isolated); ++ fast_isolate_around(cc, low_pfn); + return low_pfn; + } + +diff --git a/mm/gup.c b/mm/gup.c +index 3b7bc2c1fd44c..eb8d7baf9e4d3 100644 +--- a/mm/gup.c ++++ b/mm/gup.c +@@ -1065,6 +1065,9 @@ static int check_vma_flags(struct vm_area_struct *vma, unsigned long gup_flags) + if (!(vm_flags & VM_WRITE)) { + if (!(gup_flags & FOLL_FORCE)) + return -EFAULT; ++ /* hugetlb does not support FOLL_FORCE|FOLL_WRITE. */ ++ if (is_vm_hugetlb_page(vma)) ++ return -EFAULT; + /* + * We used to let the write,force case do COW in a + * VM_MAYWRITE VM_SHARED !VM_WRITE vma, so ptrace could +diff --git a/mm/kmsan/hooks.c b/mm/kmsan/hooks.c +index 35f6b6e6a908c..3807502766a3e 100644 +--- a/mm/kmsan/hooks.c ++++ b/mm/kmsan/hooks.c +@@ -260,6 +260,7 @@ void kmsan_handle_urb(const struct urb *urb, bool is_out) + urb->transfer_buffer_length, + /*checked*/ false); + } ++EXPORT_SYMBOL_GPL(kmsan_handle_urb); + + static void kmsan_handle_dma_page(const void *addr, size_t size, + enum dma_data_direction dir) +diff --git a/mm/kmsan/kmsan_test.c b/mm/kmsan/kmsan_test.c +index 9a29ea2dbfb9b..1328636cbd6cd 100644 +--- a/mm/kmsan/kmsan_test.c ++++ b/mm/kmsan/kmsan_test.c +@@ -22,6 +22,7 @@ + #include <linux/spinlock.h> + #include <linux/string.h> + #include <linux/tracepoint.h> ++#include <linux/vmalloc.h> + #include <trace/events/printk.h> + + static DEFINE_PER_CPU(int, per_cpu_var); +diff --git a/mm/mempolicy.c b/mm/mempolicy.c +index 61aa9aedb7289..02c8a712282f1 100644 +--- a/mm/mempolicy.c ++++ b/mm/mempolicy.c +@@ -1540,6 +1540,7 @@ SYSCALL_DEFINE4(set_mempolicy_home_node, unsigned long, start, unsigned long, le + * the home node for vmas we already updated before. + */ + if (new->mode != MPOL_BIND && new->mode != MPOL_PREFERRED_MANY) { ++ mpol_put(new); + err = -EOPNOTSUPP; + break; + } +diff --git a/mm/mremap.c b/mm/mremap.c +index e465ffe279bb0..fe587c5d65913 100644 +--- a/mm/mremap.c ++++ b/mm/mremap.c +@@ -1016,7 +1016,8 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len, + long pages = (new_len - old_len) >> PAGE_SHIFT; + unsigned long extension_start = addr + old_len; + unsigned long extension_end = addr + new_len; +- pgoff_t extension_pgoff = vma->vm_pgoff + (old_len >> PAGE_SHIFT); ++ pgoff_t extension_pgoff = vma->vm_pgoff + ++ ((extension_start - vma->vm_start) >> PAGE_SHIFT); + + if (vma->vm_flags & VM_ACCOUNT) { + if (security_vm_enough_memory_mm(mm, pages)) { +diff --git a/net/802/mrp.c b/net/802/mrp.c +index 155f74d8b14f4..6c927d4b35f06 100644 +--- a/net/802/mrp.c ++++ b/net/802/mrp.c +@@ -606,7 +606,10 @@ static void mrp_join_timer(struct timer_list *t) + spin_unlock(&app->lock); + + mrp_queue_xmit(app); +- mrp_join_timer_arm(app); ++ spin_lock(&app->lock); ++ if (likely(app->active)) ++ mrp_join_timer_arm(app); ++ spin_unlock(&app->lock); + } + + static void mrp_periodic_timer_arm(struct mrp_applicant *app) +@@ -620,11 +623,12 @@ static void mrp_periodic_timer(struct timer_list *t) + struct mrp_applicant *app = from_timer(app, t, periodic_timer); + + spin_lock(&app->lock); +- mrp_mad_event(app, MRP_EVENT_PERIODIC); +- mrp_pdu_queue(app); ++ if (likely(app->active)) { ++ mrp_mad_event(app, MRP_EVENT_PERIODIC); ++ mrp_pdu_queue(app); ++ mrp_periodic_timer_arm(app); ++ } + spin_unlock(&app->lock); +- +- mrp_periodic_timer_arm(app); + } + + static int mrp_pdu_parse_end_mark(struct sk_buff *skb, int *offset) +@@ -872,6 +876,7 @@ int mrp_init_applicant(struct net_device *dev, struct mrp_application *appl) + app->dev = dev; + app->app = appl; + app->mad = RB_ROOT; ++ app->active = true; + spin_lock_init(&app->lock); + skb_queue_head_init(&app->queue); + rcu_assign_pointer(dev->mrp_port->applicants[appl->type], app); +@@ -900,6 +905,9 @@ void mrp_uninit_applicant(struct net_device *dev, struct mrp_application *appl) + + RCU_INIT_POINTER(port->applicants[appl->type], NULL); + ++ spin_lock_bh(&app->lock); ++ app->active = false; ++ spin_unlock_bh(&app->lock); + /* Delete timer and generate a final TX event to flush out + * all pending messages before the applicant is gone. + */ +diff --git a/net/9p/client.c b/net/9p/client.c +index aaa37b07e30a5..b554f8357f967 100644 +--- a/net/9p/client.c ++++ b/net/9p/client.c +@@ -297,6 +297,11 @@ p9_tag_alloc(struct p9_client *c, int8_t type, uint t_size, uint r_size, + p9pdu_reset(&req->rc); + req->t_err = 0; + req->status = REQ_STATUS_ALLOC; ++ /* refcount needs to be set to 0 before inserting into the idr ++ * so p9_tag_lookup does not accept a request that is not fully ++ * initialized. refcount_set to 2 below will mark request ready. ++ */ ++ refcount_set(&req->refcount, 0); + init_waitqueue_head(&req->wq); + INIT_LIST_HEAD(&req->req_list); + +diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c +index a6c12863a2532..8aab2e882958c 100644 +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -1881,7 +1881,7 @@ static int hci_create_cis_sync(struct hci_dev *hdev, void *data) + continue; + + /* Check if all CIS(s) belonging to a CIG are ready */ +- if (conn->link->state != BT_CONNECTED || ++ if (!conn->link || conn->link->state != BT_CONNECTED || + conn->state != BT_CONNECT) { + cmd.cp.num_cis = 0; + break; +diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c +index d97fac4f71303..b65c3aabcd536 100644 +--- a/net/bluetooth/hci_core.c ++++ b/net/bluetooth/hci_core.c +@@ -2660,7 +2660,7 @@ int hci_register_dev(struct hci_dev *hdev) + + error = hci_register_suspend_notifier(hdev); + if (error) +- goto err_wqueue; ++ BT_WARN("register suspend notifier failed error:%d\n", error); + + queue_work(hdev->req_workqueue, &hdev->power_on); + +@@ -3985,7 +3985,7 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status, + *req_complete_skb = bt_cb(skb)->hci.req_complete_skb; + else + *req_complete = bt_cb(skb)->hci.req_complete; +- kfree_skb(skb); ++ dev_kfree_skb_irq(skb); + } + spin_unlock_irqrestore(&hdev->cmd_q.lock, flags); + } +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index 1fc693122a47a..3a68d9bc43b8f 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -4261,7 +4261,7 @@ static int hci_read_local_pairing_opts_sync(struct hci_dev *hdev) + /* Get MWS transport configuration if the HCI command is supported */ + static int hci_get_mws_transport_config_sync(struct hci_dev *hdev) + { +- if (!(hdev->commands[30] & 0x08)) ++ if (!mws_transport_config_capable(hdev)) + return 0; + + return __hci_cmd_sync_status(hdev, HCI_OP_GET_MWS_TRANSPORT_CONFIG, +diff --git a/net/bluetooth/lib.c b/net/bluetooth/lib.c +index 469a0c95b6e8a..53a796ac078c3 100644 +--- a/net/bluetooth/lib.c ++++ b/net/bluetooth/lib.c +@@ -170,7 +170,7 @@ __u8 bt_status(int err) + case -EMLINK: + return 0x09; + +- case EALREADY: ++ case -EALREADY: + return 0x0b; + + case -EBUSY: +@@ -191,7 +191,7 @@ __u8 bt_status(int err) + case -ECONNABORTED: + return 0x16; + +- case ELOOP: ++ case -ELOOP: + return 0x17; + + case -EPROTONOSUPPORT: +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index a92e7e485feba..0dd30a3beb776 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -8859,7 +8859,7 @@ static int add_ext_adv_params(struct sock *sk, struct hci_dev *hdev, + * extra parameters we don't know about will be ignored in this request. + */ + if (data_len < MGMT_ADD_EXT_ADV_PARAMS_MIN_SIZE) +- return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING, ++ return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_PARAMS, + MGMT_STATUS_INVALID_PARAMS); + + flags = __le32_to_cpu(cp->flags); +diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c +index 7324764384b67..8d6fce9005bdd 100644 +--- a/net/bluetooth/rfcomm/core.c ++++ b/net/bluetooth/rfcomm/core.c +@@ -590,7 +590,7 @@ int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb) + + ret = rfcomm_dlc_send_frag(d, frag); + if (ret < 0) { +- kfree_skb(frag); ++ dev_kfree_skb_irq(frag); + goto unlock; + } + +diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c +index fcb3e6c5e03c0..6094ef7cffcd2 100644 +--- a/net/bpf/test_run.c ++++ b/net/bpf/test_run.c +@@ -980,9 +980,6 @@ static int convert___skb_to_skb(struct sk_buff *skb, struct __sk_buff *__skb) + { + struct qdisc_skb_cb *cb = (struct qdisc_skb_cb *)skb->cb; + +- if (!skb->len) +- return -EINVAL; +- + if (!__skb) + return 0; + +diff --git a/net/core/dev.c b/net/core/dev.c +index 3be256051e99b..70e06853ba255 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -10379,24 +10379,16 @@ void netdev_run_todo(void) + void netdev_stats_to_stats64(struct rtnl_link_stats64 *stats64, + const struct net_device_stats *netdev_stats) + { +-#if BITS_PER_LONG == 64 +- BUILD_BUG_ON(sizeof(*stats64) < sizeof(*netdev_stats)); +- memcpy(stats64, netdev_stats, sizeof(*netdev_stats)); +- /* zero out counters that only exist in rtnl_link_stats64 */ +- memset((char *)stats64 + sizeof(*netdev_stats), 0, +- sizeof(*stats64) - sizeof(*netdev_stats)); +-#else +- size_t i, n = sizeof(*netdev_stats) / sizeof(unsigned long); +- const unsigned long *src = (const unsigned long *)netdev_stats; ++ size_t i, n = sizeof(*netdev_stats) / sizeof(atomic_long_t); ++ const atomic_long_t *src = (atomic_long_t *)netdev_stats; + u64 *dst = (u64 *)stats64; + + BUILD_BUG_ON(n > sizeof(*stats64) / sizeof(u64)); + for (i = 0; i < n; i++) +- dst[i] = src[i]; ++ dst[i] = atomic_long_read(&src[i]); + /* zero out counters that only exist in rtnl_link_stats64 */ + memset((char *)stats64 + n * sizeof(u64), 0, + sizeof(*stats64) - n * sizeof(u64)); +-#endif + } + EXPORT_SYMBOL(netdev_stats_to_stats64); + +diff --git a/net/core/devlink.c b/net/core/devlink.c +index 89baa7c0938b9..2aa77d4b80d0a 100644 +--- a/net/core/devlink.c ++++ b/net/core/devlink.c +@@ -1505,10 +1505,13 @@ static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg, + continue; + } + ++ devl_lock(devlink); + err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, NLM_F_MULTI); ++ devl_unlock(devlink); + devlink_put(devlink); ++ + if (err) + goto out; + idx++; +@@ -11435,8 +11438,10 @@ void devl_region_destroy(struct devlink_region *region) + devl_assert_locked(devlink); + + /* Free all snapshots of region */ ++ mutex_lock(®ion->snapshot_lock); + list_for_each_entry_safe(snapshot, ts, ®ion->snapshot_list, list) + devlink_region_snapshot_del(region, snapshot); ++ mutex_unlock(®ion->snapshot_lock); + + list_del(®ion->list); + mutex_destroy(®ion->snapshot_lock); +diff --git a/net/core/filter.c b/net/core/filter.c +index bb0136e7a8e42..a368edd9057c7 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -80,6 +80,7 @@ + #include <net/tls.h> + #include <net/xdp.h> + #include <net/mptcp.h> ++#include <net/netfilter/nf_conntrack_bpf.h> + + static const struct bpf_func_proto * + bpf_sk_base_func_proto(enum bpf_func_id func_id); +@@ -2124,8 +2125,17 @@ static int __bpf_redirect_no_mac(struct sk_buff *skb, struct net_device *dev, + { + unsigned int mlen = skb_network_offset(skb); + ++ if (unlikely(skb->len <= mlen)) { ++ kfree_skb(skb); ++ return -ERANGE; ++ } ++ + if (mlen) { + __skb_pull(skb, mlen); ++ if (unlikely(!skb->len)) { ++ kfree_skb(skb); ++ return -ERANGE; ++ } + + /* At ingress, the mac header has already been pulled once. + * At egress, skb_pospull_rcsum has to be done in case that +@@ -2145,7 +2155,7 @@ static int __bpf_redirect_common(struct sk_buff *skb, struct net_device *dev, + u32 flags) + { + /* Verify that a link layer header is carried */ +- if (unlikely(skb->mac_header >= skb->network_header)) { ++ if (unlikely(skb->mac_header >= skb->network_header || skb->len == 0)) { + kfree_skb(skb); + return -ERANGE; + } +@@ -7983,6 +7993,19 @@ xdp_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) + default: + return bpf_sk_base_func_proto(func_id); + } ++ ++#if IS_MODULE(CONFIG_NF_CONNTRACK) && IS_ENABLED(CONFIG_DEBUG_INFO_BTF_MODULES) ++ /* The nf_conn___init type is used in the NF_CONNTRACK kfuncs. The ++ * kfuncs are defined in two different modules, and we want to be able ++ * to use them interchangably with the same BTF type ID. Because modules ++ * can't de-duplicate BTF IDs between each other, we need the type to be ++ * referenced in the vmlinux BTF or the verifier will get confused about ++ * the different types. So we add this dummy type reference which will ++ * be included in vmlinux BTF, allowing both modules to refer to the ++ * same type ID. ++ */ ++ BTF_TYPE_EMIT(struct nf_conn___init); ++#endif + } + + const struct bpf_func_proto bpf_sock_map_update_proto __weak; +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index 88fa40571d0c7..759bede0b3dd6 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -2416,6 +2416,9 @@ void *__pskb_pull_tail(struct sk_buff *skb, int delta) + insp = list; + } else { + /* Eaten partially. */ ++ if (skb_is_gso(skb) && !list->head_frag && ++ skb_headlen(list)) ++ skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; + + if (skb_shared(list)) { + /* Sucks! We need to fork list. :-( */ +diff --git a/net/core/skmsg.c b/net/core/skmsg.c +index e6b9ced3eda82..53d0251788aa2 100644 +--- a/net/core/skmsg.c ++++ b/net/core/skmsg.c +@@ -886,13 +886,16 @@ int sk_psock_msg_verdict(struct sock *sk, struct sk_psock *psock, + ret = sk_psock_map_verd(ret, msg->sk_redir); + psock->apply_bytes = msg->apply_bytes; + if (ret == __SK_REDIRECT) { +- if (psock->sk_redir) ++ if (psock->sk_redir) { + sock_put(psock->sk_redir); +- psock->sk_redir = msg->sk_redir; +- if (!psock->sk_redir) { ++ psock->sk_redir = NULL; ++ } ++ if (!msg->sk_redir) { + ret = __SK_DROP; + goto out; + } ++ psock->redir_ingress = sk_msg_to_ingress(msg); ++ psock->sk_redir = msg->sk_redir; + sock_hold(psock->sk_redir); + } + out: +diff --git a/net/core/sock.c b/net/core/sock.c +index a3ba0358c77c0..30407b2dd2ac4 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -1436,7 +1436,7 @@ set_sndbuf: + break; + } + case SO_INCOMING_CPU: +- WRITE_ONCE(sk->sk_incoming_cpu, val); ++ reuseport_update_incoming_cpu(sk, val); + break; + + case SO_CNX_ADVICE: +diff --git a/net/core/sock_map.c b/net/core/sock_map.c +index 81beb16ab1ebf..22fa2c5bc6ec9 100644 +--- a/net/core/sock_map.c ++++ b/net/core/sock_map.c +@@ -349,11 +349,13 @@ static void sock_map_free(struct bpf_map *map) + + sk = xchg(psk, NULL); + if (sk) { ++ sock_hold(sk); + lock_sock(sk); + rcu_read_lock(); + sock_map_unref(sk, psk); + rcu_read_unlock(); + release_sock(sk); ++ sock_put(sk); + } + } + +diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c +index fb90e1e00773b..5a165286e4d8e 100644 +--- a/net/core/sock_reuseport.c ++++ b/net/core/sock_reuseport.c +@@ -37,6 +37,70 @@ void reuseport_has_conns_set(struct sock *sk) + } + EXPORT_SYMBOL(reuseport_has_conns_set); + ++static void __reuseport_get_incoming_cpu(struct sock_reuseport *reuse) ++{ ++ /* Paired with READ_ONCE() in reuseport_select_sock_by_hash(). */ ++ WRITE_ONCE(reuse->incoming_cpu, reuse->incoming_cpu + 1); ++} ++ ++static void __reuseport_put_incoming_cpu(struct sock_reuseport *reuse) ++{ ++ /* Paired with READ_ONCE() in reuseport_select_sock_by_hash(). */ ++ WRITE_ONCE(reuse->incoming_cpu, reuse->incoming_cpu - 1); ++} ++ ++static void reuseport_get_incoming_cpu(struct sock *sk, struct sock_reuseport *reuse) ++{ ++ if (sk->sk_incoming_cpu >= 0) ++ __reuseport_get_incoming_cpu(reuse); ++} ++ ++static void reuseport_put_incoming_cpu(struct sock *sk, struct sock_reuseport *reuse) ++{ ++ if (sk->sk_incoming_cpu >= 0) ++ __reuseport_put_incoming_cpu(reuse); ++} ++ ++void reuseport_update_incoming_cpu(struct sock *sk, int val) ++{ ++ struct sock_reuseport *reuse; ++ int old_sk_incoming_cpu; ++ ++ if (unlikely(!rcu_access_pointer(sk->sk_reuseport_cb))) { ++ /* Paired with REAE_ONCE() in sk_incoming_cpu_update() ++ * and compute_score(). ++ */ ++ WRITE_ONCE(sk->sk_incoming_cpu, val); ++ return; ++ } ++ ++ spin_lock_bh(&reuseport_lock); ++ ++ /* This must be done under reuseport_lock to avoid a race with ++ * reuseport_grow(), which accesses sk->sk_incoming_cpu without ++ * lock_sock() when detaching a shutdown()ed sk. ++ * ++ * Paired with READ_ONCE() in reuseport_select_sock_by_hash(). ++ */ ++ old_sk_incoming_cpu = sk->sk_incoming_cpu; ++ WRITE_ONCE(sk->sk_incoming_cpu, val); ++ ++ reuse = rcu_dereference_protected(sk->sk_reuseport_cb, ++ lockdep_is_held(&reuseport_lock)); ++ ++ /* reuseport_grow() has detached a closed sk. */ ++ if (!reuse) ++ goto out; ++ ++ if (old_sk_incoming_cpu < 0 && val >= 0) ++ __reuseport_get_incoming_cpu(reuse); ++ else if (old_sk_incoming_cpu >= 0 && val < 0) ++ __reuseport_put_incoming_cpu(reuse); ++ ++out: ++ spin_unlock_bh(&reuseport_lock); ++} ++ + static int reuseport_sock_index(struct sock *sk, + const struct sock_reuseport *reuse, + bool closed) +@@ -64,6 +128,7 @@ static void __reuseport_add_sock(struct sock *sk, + /* paired with smp_rmb() in reuseport_(select|migrate)_sock() */ + smp_wmb(); + reuse->num_socks++; ++ reuseport_get_incoming_cpu(sk, reuse); + } + + static bool __reuseport_detach_sock(struct sock *sk, +@@ -76,6 +141,7 @@ static bool __reuseport_detach_sock(struct sock *sk, + + reuse->socks[i] = reuse->socks[reuse->num_socks - 1]; + reuse->num_socks--; ++ reuseport_put_incoming_cpu(sk, reuse); + + return true; + } +@@ -86,6 +152,7 @@ static void __reuseport_add_closed_sock(struct sock *sk, + reuse->socks[reuse->max_socks - reuse->num_closed_socks - 1] = sk; + /* paired with READ_ONCE() in inet_csk_bind_conflict() */ + WRITE_ONCE(reuse->num_closed_socks, reuse->num_closed_socks + 1); ++ reuseport_get_incoming_cpu(sk, reuse); + } + + static bool __reuseport_detach_closed_sock(struct sock *sk, +@@ -99,6 +166,7 @@ static bool __reuseport_detach_closed_sock(struct sock *sk, + reuse->socks[i] = reuse->socks[reuse->max_socks - reuse->num_closed_socks]; + /* paired with READ_ONCE() in inet_csk_bind_conflict() */ + WRITE_ONCE(reuse->num_closed_socks, reuse->num_closed_socks - 1); ++ reuseport_put_incoming_cpu(sk, reuse); + + return true; + } +@@ -166,6 +234,7 @@ int reuseport_alloc(struct sock *sk, bool bind_inany) + reuse->bind_inany = bind_inany; + reuse->socks[0] = sk; + reuse->num_socks = 1; ++ reuseport_get_incoming_cpu(sk, reuse); + rcu_assign_pointer(sk->sk_reuseport_cb, reuse); + + out: +@@ -209,6 +278,7 @@ static struct sock_reuseport *reuseport_grow(struct sock_reuseport *reuse) + more_reuse->reuseport_id = reuse->reuseport_id; + more_reuse->bind_inany = reuse->bind_inany; + more_reuse->has_conns = reuse->has_conns; ++ more_reuse->incoming_cpu = reuse->incoming_cpu; + + memcpy(more_reuse->socks, reuse->socks, + reuse->num_socks * sizeof(struct sock *)); +@@ -458,18 +528,32 @@ static struct sock *run_bpf_filter(struct sock_reuseport *reuse, u16 socks, + static struct sock *reuseport_select_sock_by_hash(struct sock_reuseport *reuse, + u32 hash, u16 num_socks) + { ++ struct sock *first_valid_sk = NULL; + int i, j; + + i = j = reciprocal_scale(hash, num_socks); +- while (reuse->socks[i]->sk_state == TCP_ESTABLISHED) { ++ do { ++ struct sock *sk = reuse->socks[i]; ++ ++ if (sk->sk_state != TCP_ESTABLISHED) { ++ /* Paired with WRITE_ONCE() in __reuseport_(get|put)_incoming_cpu(). */ ++ if (!READ_ONCE(reuse->incoming_cpu)) ++ return sk; ++ ++ /* Paired with WRITE_ONCE() in reuseport_update_incoming_cpu(). */ ++ if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id()) ++ return sk; ++ ++ if (!first_valid_sk) ++ first_valid_sk = sk; ++ } ++ + i++; + if (i >= num_socks) + i = 0; +- if (i == j) +- return NULL; +- } ++ } while (i != j); + +- return reuse->socks[i]; ++ return first_valid_sk; + } + + /** +diff --git a/net/core/stream.c b/net/core/stream.c +index 75fded8495f5b..516895f482356 100644 +--- a/net/core/stream.c ++++ b/net/core/stream.c +@@ -196,6 +196,12 @@ void sk_stream_kill_queues(struct sock *sk) + /* First the read buffer. */ + __skb_queue_purge(&sk->sk_receive_queue); + ++ /* Next, the error queue. ++ * We need to use queue lock, because other threads might ++ * add packets to the queue without socket lock being held. ++ */ ++ skb_queue_purge(&sk->sk_error_queue); ++ + /* Next, the write queue. */ + WARN_ON_ONCE(!skb_queue_empty(&sk->sk_write_queue)); + +diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c +index 34e5ec5d3e236..89371b16416e2 100644 +--- a/net/dsa/tag_8021q.c ++++ b/net/dsa/tag_8021q.c +@@ -398,6 +398,7 @@ static void dsa_tag_8021q_teardown(struct dsa_switch *ds) + int dsa_tag_8021q_register(struct dsa_switch *ds, __be16 proto) + { + struct dsa_8021q_context *ctx; ++ int err; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) +@@ -410,7 +411,15 @@ int dsa_tag_8021q_register(struct dsa_switch *ds, __be16 proto) + + ds->tag_8021q_ctx = ctx; + +- return dsa_tag_8021q_setup(ds); ++ err = dsa_tag_8021q_setup(ds); ++ if (err) ++ goto err_free; ++ ++ return 0; ++ ++err_free: ++ kfree(ctx); ++ return err; + } + EXPORT_SYMBOL_GPL(dsa_tag_8021q_register); + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index 57e7238a4136b..81fe2422fe58a 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -2008,7 +2008,8 @@ static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) + } else { + /* Driver expects to be called at twice the frequency in rc */ + int n = rc * 2, interval = HZ / n; +- u64 count = n * id.data, i = 0; ++ u64 count = mul_u32_u32(n, id.data); ++ u64 i = 0; + + do { + rtnl_lock(); +diff --git a/net/hsr/hsr_debugfs.c b/net/hsr/hsr_debugfs.c +index de476a4176314..1a195efc79cd1 100644 +--- a/net/hsr/hsr_debugfs.c ++++ b/net/hsr/hsr_debugfs.c +@@ -9,7 +9,6 @@ + #include <linux/module.h> + #include <linux/errno.h> + #include <linux/debugfs.h> +-#include <linux/jhash.h> + #include "hsr_main.h" + #include "hsr_framereg.h" + +@@ -21,7 +20,6 @@ hsr_node_table_show(struct seq_file *sfp, void *data) + { + struct hsr_priv *priv = (struct hsr_priv *)sfp->private; + struct hsr_node *node; +- int i; + + seq_printf(sfp, "Node Table entries for (%s) device\n", + (priv->prot_version == PRP_V1 ? "PRP" : "HSR")); +@@ -33,28 +31,22 @@ hsr_node_table_show(struct seq_file *sfp, void *data) + seq_puts(sfp, "DAN-H\n"); + + rcu_read_lock(); +- +- for (i = 0 ; i < priv->hash_buckets; i++) { +- hlist_for_each_entry_rcu(node, &priv->node_db[i], mac_list) { +- /* skip self node */ +- if (hsr_addr_is_self(priv, node->macaddress_A)) +- continue; +- seq_printf(sfp, "%pM ", &node->macaddress_A[0]); +- seq_printf(sfp, "%pM ", &node->macaddress_B[0]); +- seq_printf(sfp, "%10lx, ", +- node->time_in[HSR_PT_SLAVE_A]); +- seq_printf(sfp, "%10lx, ", +- node->time_in[HSR_PT_SLAVE_B]); +- seq_printf(sfp, "%14x, ", node->addr_B_port); +- +- if (priv->prot_version == PRP_V1) +- seq_printf(sfp, "%5x, %5x, %5x\n", +- node->san_a, node->san_b, +- (node->san_a == 0 && +- node->san_b == 0)); +- else +- seq_printf(sfp, "%5x\n", 1); +- } ++ list_for_each_entry_rcu(node, &priv->node_db, mac_list) { ++ /* skip self node */ ++ if (hsr_addr_is_self(priv, node->macaddress_A)) ++ continue; ++ seq_printf(sfp, "%pM ", &node->macaddress_A[0]); ++ seq_printf(sfp, "%pM ", &node->macaddress_B[0]); ++ seq_printf(sfp, "%10lx, ", node->time_in[HSR_PT_SLAVE_A]); ++ seq_printf(sfp, "%10lx, ", node->time_in[HSR_PT_SLAVE_B]); ++ seq_printf(sfp, "%14x, ", node->addr_B_port); ++ ++ if (priv->prot_version == PRP_V1) ++ seq_printf(sfp, "%5x, %5x, %5x\n", ++ node->san_a, node->san_b, ++ (node->san_a == 0 && node->san_b == 0)); ++ else ++ seq_printf(sfp, "%5x\n", 1); + } + rcu_read_unlock(); + return 0; +diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c +index 6ffef47e9be55..b1e86a7265b32 100644 +--- a/net/hsr/hsr_device.c ++++ b/net/hsr/hsr_device.c +@@ -219,7 +219,9 @@ static netdev_tx_t hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev) + skb->dev = master->dev; + skb_reset_mac_header(skb); + skb_reset_mac_len(skb); ++ spin_lock_bh(&hsr->seqnr_lock); + hsr_forward_skb(skb, master); ++ spin_unlock_bh(&hsr->seqnr_lock); + } else { + dev_core_stats_tx_dropped_inc(dev); + dev_kfree_skb_any(skb); +@@ -278,7 +280,6 @@ static void send_hsr_supervision_frame(struct hsr_port *master, + __u8 type = HSR_TLV_LIFE_CHECK; + struct hsr_sup_payload *hsr_sp; + struct hsr_sup_tag *hsr_stag; +- unsigned long irqflags; + struct sk_buff *skb; + + *interval = msecs_to_jiffies(HSR_LIFE_CHECK_INTERVAL); +@@ -299,7 +300,7 @@ static void send_hsr_supervision_frame(struct hsr_port *master, + set_hsr_stag_HSR_ver(hsr_stag, hsr->prot_version); + + /* From HSRv1 on we have separate supervision sequence numbers. */ +- spin_lock_irqsave(&master->hsr->seqnr_lock, irqflags); ++ spin_lock_bh(&hsr->seqnr_lock); + if (hsr->prot_version > 0) { + hsr_stag->sequence_nr = htons(hsr->sup_sequence_nr); + hsr->sup_sequence_nr++; +@@ -307,7 +308,6 @@ static void send_hsr_supervision_frame(struct hsr_port *master, + hsr_stag->sequence_nr = htons(hsr->sequence_nr); + hsr->sequence_nr++; + } +- spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags); + + hsr_stag->tlv.HSR_TLV_type = type; + /* TODO: Why 12 in HSRv0? */ +@@ -318,11 +318,13 @@ static void send_hsr_supervision_frame(struct hsr_port *master, + hsr_sp = skb_put(skb, sizeof(struct hsr_sup_payload)); + ether_addr_copy(hsr_sp->macaddress_A, master->dev->dev_addr); + +- if (skb_put_padto(skb, ETH_ZLEN)) ++ if (skb_put_padto(skb, ETH_ZLEN)) { ++ spin_unlock_bh(&hsr->seqnr_lock); + return; ++ } + + hsr_forward_skb(skb, master); +- ++ spin_unlock_bh(&hsr->seqnr_lock); + return; + } + +@@ -332,7 +334,6 @@ static void send_prp_supervision_frame(struct hsr_port *master, + struct hsr_priv *hsr = master->hsr; + struct hsr_sup_payload *hsr_sp; + struct hsr_sup_tag *hsr_stag; +- unsigned long irqflags; + struct sk_buff *skb; + + skb = hsr_init_skb(master); +@@ -347,7 +348,7 @@ static void send_prp_supervision_frame(struct hsr_port *master, + set_hsr_stag_HSR_ver(hsr_stag, (hsr->prot_version ? 1 : 0)); + + /* From HSRv1 on we have separate supervision sequence numbers. */ +- spin_lock_irqsave(&master->hsr->seqnr_lock, irqflags); ++ spin_lock_bh(&hsr->seqnr_lock); + hsr_stag->sequence_nr = htons(hsr->sup_sequence_nr); + hsr->sup_sequence_nr++; + hsr_stag->tlv.HSR_TLV_type = PRP_TLV_LIFE_CHECK_DD; +@@ -358,13 +359,12 @@ static void send_prp_supervision_frame(struct hsr_port *master, + ether_addr_copy(hsr_sp->macaddress_A, master->dev->dev_addr); + + if (skb_put_padto(skb, ETH_ZLEN)) { +- spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags); ++ spin_unlock_bh(&hsr->seqnr_lock); + return; + } + +- spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags); +- + hsr_forward_skb(skb, master); ++ spin_unlock_bh(&hsr->seqnr_lock); + } + + /* Announce (supervision frame) timer function +@@ -444,7 +444,7 @@ void hsr_dev_setup(struct net_device *dev) + dev->header_ops = &hsr_header_ops; + dev->netdev_ops = &hsr_device_ops; + SET_NETDEV_DEVTYPE(dev, &hsr_type); +- dev->priv_flags |= IFF_NO_QUEUE; ++ dev->priv_flags |= IFF_NO_QUEUE | IFF_DISABLE_NETPOLL; + + dev->needs_free_netdev = true; + +@@ -485,16 +485,12 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], + { + bool unregister = false; + struct hsr_priv *hsr; +- int res, i; ++ int res; + + hsr = netdev_priv(hsr_dev); + INIT_LIST_HEAD(&hsr->ports); +- INIT_HLIST_HEAD(&hsr->self_node_db); +- hsr->hash_buckets = HSR_HSIZE; +- get_random_bytes(&hsr->hash_seed, sizeof(hsr->hash_seed)); +- for (i = 0; i < hsr->hash_buckets; i++) +- INIT_HLIST_HEAD(&hsr->node_db[i]); +- ++ INIT_LIST_HEAD(&hsr->node_db); ++ INIT_LIST_HEAD(&hsr->self_node_db); + spin_lock_init(&hsr->list_lock); + + eth_hw_addr_set(hsr_dev, slave[0]->dev_addr); +diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c +index 56bb27d67a2ee..629daacc96071 100644 +--- a/net/hsr/hsr_forward.c ++++ b/net/hsr/hsr_forward.c +@@ -500,7 +500,6 @@ static void handle_std_frame(struct sk_buff *skb, + { + struct hsr_port *port = frame->port_rcv; + struct hsr_priv *hsr = port->hsr; +- unsigned long irqflags; + + frame->skb_hsr = NULL; + frame->skb_prp = NULL; +@@ -510,10 +509,9 @@ static void handle_std_frame(struct sk_buff *skb, + frame->is_from_san = true; + } else { + /* Sequence nr for the master node */ +- spin_lock_irqsave(&hsr->seqnr_lock, irqflags); ++ lockdep_assert_held(&hsr->seqnr_lock); + frame->sequence_nr = hsr->sequence_nr; + hsr->sequence_nr++; +- spin_unlock_irqrestore(&hsr->seqnr_lock, irqflags); + } + } + +@@ -571,23 +569,20 @@ static int fill_frame_info(struct hsr_frame_info *frame, + struct ethhdr *ethhdr; + __be16 proto; + int ret; +- u32 hash; + + /* Check if skb contains ethhdr */ + if (skb->mac_len < sizeof(struct ethhdr)) + return -EINVAL; + + memset(frame, 0, sizeof(*frame)); +- +- ethhdr = (struct ethhdr *)skb_mac_header(skb); +- hash = hsr_mac_hash(port->hsr, ethhdr->h_source); + frame->is_supervision = is_supervision_frame(port->hsr, skb); +- frame->node_src = hsr_get_node(port, &hsr->node_db[hash], skb, ++ frame->node_src = hsr_get_node(port, &hsr->node_db, skb, + frame->is_supervision, + port->type); + if (!frame->node_src) + return -1; /* Unknown node and !is_supervision, or no mem */ + ++ ethhdr = (struct ethhdr *)skb_mac_header(skb); + frame->is_vlan = false; + proto = ethhdr->h_proto; + +@@ -617,11 +612,13 @@ void hsr_forward_skb(struct sk_buff *skb, struct hsr_port *port) + { + struct hsr_frame_info frame; + ++ rcu_read_lock(); + if (fill_frame_info(&frame, skb, port) < 0) + goto out_drop; + + hsr_register_frame_in(frame.node_src, port, frame.sequence_nr); + hsr_forward_do(&frame); ++ rcu_read_unlock(); + /* Gets called for ingress frames as well as egress from master port. + * So check and increment stats for master port only here. + */ +@@ -636,6 +633,7 @@ void hsr_forward_skb(struct sk_buff *skb, struct hsr_port *port) + return; + + out_drop: ++ rcu_read_unlock(); + port->dev->stats.tx_dropped++; + kfree_skb(skb); + } +diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c +index 584e217887997..39a6088080e93 100644 +--- a/net/hsr/hsr_framereg.c ++++ b/net/hsr/hsr_framereg.c +@@ -15,37 +15,10 @@ + #include <linux/etherdevice.h> + #include <linux/slab.h> + #include <linux/rculist.h> +-#include <linux/jhash.h> + #include "hsr_main.h" + #include "hsr_framereg.h" + #include "hsr_netlink.h" + +-#ifdef CONFIG_LOCKDEP +-int lockdep_hsr_is_held(spinlock_t *lock) +-{ +- return lockdep_is_held(lock); +-} +-#endif +- +-u32 hsr_mac_hash(struct hsr_priv *hsr, const unsigned char *addr) +-{ +- u32 hash = jhash(addr, ETH_ALEN, hsr->hash_seed); +- +- return reciprocal_scale(hash, hsr->hash_buckets); +-} +- +-struct hsr_node *hsr_node_get_first(struct hlist_head *head, spinlock_t *lock) +-{ +- struct hlist_node *first; +- +- first = rcu_dereference_bh_check(hlist_first_rcu(head), +- lockdep_hsr_is_held(lock)); +- if (first) +- return hlist_entry(first, struct hsr_node, mac_list); +- +- return NULL; +-} +- + /* seq_nr_after(a, b) - return true if a is after (higher in sequence than) b, + * false otherwise. + */ +@@ -67,7 +40,8 @@ bool hsr_addr_is_self(struct hsr_priv *hsr, unsigned char *addr) + { + struct hsr_node *node; + +- node = hsr_node_get_first(&hsr->self_node_db, &hsr->list_lock); ++ node = list_first_or_null_rcu(&hsr->self_node_db, struct hsr_node, ++ mac_list); + if (!node) { + WARN_ONCE(1, "HSR: No self node\n"); + return false; +@@ -83,12 +57,12 @@ bool hsr_addr_is_self(struct hsr_priv *hsr, unsigned char *addr) + + /* Search for mac entry. Caller must hold rcu read lock. + */ +-static struct hsr_node *find_node_by_addr_A(struct hlist_head *node_db, ++static struct hsr_node *find_node_by_addr_A(struct list_head *node_db, + const unsigned char addr[ETH_ALEN]) + { + struct hsr_node *node; + +- hlist_for_each_entry_rcu(node, node_db, mac_list) { ++ list_for_each_entry_rcu(node, node_db, mac_list) { + if (ether_addr_equal(node->macaddress_A, addr)) + return node; + } +@@ -103,7 +77,7 @@ int hsr_create_self_node(struct hsr_priv *hsr, + const unsigned char addr_a[ETH_ALEN], + const unsigned char addr_b[ETH_ALEN]) + { +- struct hlist_head *self_node_db = &hsr->self_node_db; ++ struct list_head *self_node_db = &hsr->self_node_db; + struct hsr_node *node, *oldnode; + + node = kmalloc(sizeof(*node), GFP_KERNEL); +@@ -114,13 +88,14 @@ int hsr_create_self_node(struct hsr_priv *hsr, + ether_addr_copy(node->macaddress_B, addr_b); + + spin_lock_bh(&hsr->list_lock); +- oldnode = hsr_node_get_first(self_node_db, &hsr->list_lock); ++ oldnode = list_first_or_null_rcu(self_node_db, ++ struct hsr_node, mac_list); + if (oldnode) { +- hlist_replace_rcu(&oldnode->mac_list, &node->mac_list); ++ list_replace_rcu(&oldnode->mac_list, &node->mac_list); + spin_unlock_bh(&hsr->list_lock); + kfree_rcu(oldnode, rcu_head); + } else { +- hlist_add_tail_rcu(&node->mac_list, self_node_db); ++ list_add_tail_rcu(&node->mac_list, self_node_db); + spin_unlock_bh(&hsr->list_lock); + } + +@@ -129,25 +104,25 @@ int hsr_create_self_node(struct hsr_priv *hsr, + + void hsr_del_self_node(struct hsr_priv *hsr) + { +- struct hlist_head *self_node_db = &hsr->self_node_db; ++ struct list_head *self_node_db = &hsr->self_node_db; + struct hsr_node *node; + + spin_lock_bh(&hsr->list_lock); +- node = hsr_node_get_first(self_node_db, &hsr->list_lock); ++ node = list_first_or_null_rcu(self_node_db, struct hsr_node, mac_list); + if (node) { +- hlist_del_rcu(&node->mac_list); ++ list_del_rcu(&node->mac_list); + kfree_rcu(node, rcu_head); + } + spin_unlock_bh(&hsr->list_lock); + } + +-void hsr_del_nodes(struct hlist_head *node_db) ++void hsr_del_nodes(struct list_head *node_db) + { + struct hsr_node *node; +- struct hlist_node *tmp; ++ struct hsr_node *tmp; + +- hlist_for_each_entry_safe(node, tmp, node_db, mac_list) +- kfree_rcu(node, rcu_head); ++ list_for_each_entry_safe(node, tmp, node_db, mac_list) ++ kfree(node); + } + + void prp_handle_san_frame(bool san, enum hsr_port_type port, +@@ -168,7 +143,7 @@ void prp_handle_san_frame(bool san, enum hsr_port_type port, + * originating from the newly added node. + */ + static struct hsr_node *hsr_add_node(struct hsr_priv *hsr, +- struct hlist_head *node_db, ++ struct list_head *node_db, + unsigned char addr[], + u16 seq_out, bool san, + enum hsr_port_type rx_port) +@@ -182,6 +157,7 @@ static struct hsr_node *hsr_add_node(struct hsr_priv *hsr, + return NULL; + + ether_addr_copy(new_node->macaddress_A, addr); ++ spin_lock_init(&new_node->seq_out_lock); + + /* We are only interested in time diffs here, so use current jiffies + * as initialization. (0 could trigger an spurious ring error warning). +@@ -198,14 +174,14 @@ static struct hsr_node *hsr_add_node(struct hsr_priv *hsr, + hsr->proto_ops->handle_san_frame(san, rx_port, new_node); + + spin_lock_bh(&hsr->list_lock); +- hlist_for_each_entry_rcu(node, node_db, mac_list, +- lockdep_hsr_is_held(&hsr->list_lock)) { ++ list_for_each_entry_rcu(node, node_db, mac_list, ++ lockdep_is_held(&hsr->list_lock)) { + if (ether_addr_equal(node->macaddress_A, addr)) + goto out; + if (ether_addr_equal(node->macaddress_B, addr)) + goto out; + } +- hlist_add_tail_rcu(&new_node->mac_list, node_db); ++ list_add_tail_rcu(&new_node->mac_list, node_db); + spin_unlock_bh(&hsr->list_lock); + return new_node; + out: +@@ -225,7 +201,7 @@ void prp_update_san_info(struct hsr_node *node, bool is_sup) + + /* Get the hsr_node from which 'skb' was sent. + */ +-struct hsr_node *hsr_get_node(struct hsr_port *port, struct hlist_head *node_db, ++struct hsr_node *hsr_get_node(struct hsr_port *port, struct list_head *node_db, + struct sk_buff *skb, bool is_sup, + enum hsr_port_type rx_port) + { +@@ -241,7 +217,7 @@ struct hsr_node *hsr_get_node(struct hsr_port *port, struct hlist_head *node_db, + + ethhdr = (struct ethhdr *)skb_mac_header(skb); + +- hlist_for_each_entry_rcu(node, node_db, mac_list) { ++ list_for_each_entry_rcu(node, node_db, mac_list) { + if (ether_addr_equal(node->macaddress_A, ethhdr->h_source)) { + if (hsr->proto_ops->update_san_info) + hsr->proto_ops->update_san_info(node, is_sup); +@@ -291,12 +267,11 @@ void hsr_handle_sup_frame(struct hsr_frame_info *frame) + struct hsr_sup_tlv *hsr_sup_tlv; + struct hsr_node *node_real; + struct sk_buff *skb = NULL; +- struct hlist_head *node_db; ++ struct list_head *node_db; + struct ethhdr *ethhdr; + int i; + unsigned int pull_size = 0; + unsigned int total_pull_size = 0; +- u32 hash; + + /* Here either frame->skb_hsr or frame->skb_prp should be + * valid as supervision frame always will have protocol +@@ -334,13 +309,11 @@ void hsr_handle_sup_frame(struct hsr_frame_info *frame) + hsr_sp = (struct hsr_sup_payload *)skb->data; + + /* Merge node_curr (registered on macaddress_B) into node_real */ +- node_db = port_rcv->hsr->node_db; +- hash = hsr_mac_hash(hsr, hsr_sp->macaddress_A); +- node_real = find_node_by_addr_A(&node_db[hash], hsr_sp->macaddress_A); ++ node_db = &port_rcv->hsr->node_db; ++ node_real = find_node_by_addr_A(node_db, hsr_sp->macaddress_A); + if (!node_real) + /* No frame received from AddrA of this node yet */ +- node_real = hsr_add_node(hsr, &node_db[hash], +- hsr_sp->macaddress_A, ++ node_real = hsr_add_node(hsr, node_db, hsr_sp->macaddress_A, + HSR_SEQNR_START - 1, true, + port_rcv->type); + if (!node_real) +@@ -374,14 +347,14 @@ void hsr_handle_sup_frame(struct hsr_frame_info *frame) + hsr_sp = (struct hsr_sup_payload *)skb->data; + + /* Check if redbox mac and node mac are equal. */ +- if (!ether_addr_equal(node_real->macaddress_A, +- hsr_sp->macaddress_A)) { ++ if (!ether_addr_equal(node_real->macaddress_A, hsr_sp->macaddress_A)) { + /* This is a redbox supervision frame for a VDAN! */ + goto done; + } + } + + ether_addr_copy(node_real->macaddress_B, ethhdr->h_source); ++ spin_lock_bh(&node_real->seq_out_lock); + for (i = 0; i < HSR_PT_PORTS; i++) { + if (!node_curr->time_in_stale[i] && + time_after(node_curr->time_in[i], node_real->time_in[i])) { +@@ -392,12 +365,16 @@ void hsr_handle_sup_frame(struct hsr_frame_info *frame) + if (seq_nr_after(node_curr->seq_out[i], node_real->seq_out[i])) + node_real->seq_out[i] = node_curr->seq_out[i]; + } ++ spin_unlock_bh(&node_real->seq_out_lock); + node_real->addr_B_port = port_rcv->type; + + spin_lock_bh(&hsr->list_lock); +- hlist_del_rcu(&node_curr->mac_list); ++ if (!node_curr->removed) { ++ list_del_rcu(&node_curr->mac_list); ++ node_curr->removed = true; ++ kfree_rcu(node_curr, rcu_head); ++ } + spin_unlock_bh(&hsr->list_lock); +- kfree_rcu(node_curr, rcu_head); + + done: + /* Push back here */ +@@ -433,7 +410,6 @@ void hsr_addr_subst_dest(struct hsr_node *node_src, struct sk_buff *skb, + struct hsr_port *port) + { + struct hsr_node *node_dst; +- u32 hash; + + if (!skb_mac_header_was_set(skb)) { + WARN_ONCE(1, "%s: Mac header not set\n", __func__); +@@ -443,8 +419,7 @@ void hsr_addr_subst_dest(struct hsr_node *node_src, struct sk_buff *skb, + if (!is_unicast_ether_addr(eth_hdr(skb)->h_dest)) + return; + +- hash = hsr_mac_hash(port->hsr, eth_hdr(skb)->h_dest); +- node_dst = find_node_by_addr_A(&port->hsr->node_db[hash], ++ node_dst = find_node_by_addr_A(&port->hsr->node_db, + eth_hdr(skb)->h_dest); + if (!node_dst) { + if (net_ratelimit()) +@@ -484,13 +459,17 @@ void hsr_register_frame_in(struct hsr_node *node, struct hsr_port *port, + int hsr_register_frame_out(struct hsr_port *port, struct hsr_node *node, + u16 sequence_nr) + { ++ spin_lock_bh(&node->seq_out_lock); + if (seq_nr_before_or_eq(sequence_nr, node->seq_out[port->type]) && + time_is_after_jiffies(node->time_out[port->type] + +- msecs_to_jiffies(HSR_ENTRY_FORGET_TIME))) ++ msecs_to_jiffies(HSR_ENTRY_FORGET_TIME))) { ++ spin_unlock_bh(&node->seq_out_lock); + return 1; ++ } + + node->time_out[port->type] = jiffies; + node->seq_out[port->type] = sequence_nr; ++ spin_unlock_bh(&node->seq_out_lock); + return 0; + } + +@@ -520,71 +499,60 @@ static struct hsr_port *get_late_port(struct hsr_priv *hsr, + void hsr_prune_nodes(struct timer_list *t) + { + struct hsr_priv *hsr = from_timer(hsr, t, prune_timer); +- struct hlist_node *tmp; + struct hsr_node *node; ++ struct hsr_node *tmp; + struct hsr_port *port; + unsigned long timestamp; + unsigned long time_a, time_b; +- int i; + + spin_lock_bh(&hsr->list_lock); ++ list_for_each_entry_safe(node, tmp, &hsr->node_db, mac_list) { ++ /* Don't prune own node. Neither time_in[HSR_PT_SLAVE_A] ++ * nor time_in[HSR_PT_SLAVE_B], will ever be updated for ++ * the master port. Thus the master node will be repeatedly ++ * pruned leading to packet loss. ++ */ ++ if (hsr_addr_is_self(hsr, node->macaddress_A)) ++ continue; ++ ++ /* Shorthand */ ++ time_a = node->time_in[HSR_PT_SLAVE_A]; ++ time_b = node->time_in[HSR_PT_SLAVE_B]; ++ ++ /* Check for timestamps old enough to risk wrap-around */ ++ if (time_after(jiffies, time_a + MAX_JIFFY_OFFSET / 2)) ++ node->time_in_stale[HSR_PT_SLAVE_A] = true; ++ if (time_after(jiffies, time_b + MAX_JIFFY_OFFSET / 2)) ++ node->time_in_stale[HSR_PT_SLAVE_B] = true; ++ ++ /* Get age of newest frame from node. ++ * At least one time_in is OK here; nodes get pruned long ++ * before both time_ins can get stale ++ */ ++ timestamp = time_a; ++ if (node->time_in_stale[HSR_PT_SLAVE_A] || ++ (!node->time_in_stale[HSR_PT_SLAVE_B] && ++ time_after(time_b, time_a))) ++ timestamp = time_b; ++ ++ /* Warn of ring error only as long as we get frames at all */ ++ if (time_is_after_jiffies(timestamp + ++ msecs_to_jiffies(1.5 * MAX_SLAVE_DIFF))) { ++ rcu_read_lock(); ++ port = get_late_port(hsr, node); ++ if (port) ++ hsr_nl_ringerror(hsr, node->macaddress_A, port); ++ rcu_read_unlock(); ++ } + +- for (i = 0; i < hsr->hash_buckets; i++) { +- hlist_for_each_entry_safe(node, tmp, &hsr->node_db[i], +- mac_list) { +- /* Don't prune own node. +- * Neither time_in[HSR_PT_SLAVE_A] +- * nor time_in[HSR_PT_SLAVE_B], will ever be updated +- * for the master port. Thus the master node will be +- * repeatedly pruned leading to packet loss. +- */ +- if (hsr_addr_is_self(hsr, node->macaddress_A)) +- continue; +- +- /* Shorthand */ +- time_a = node->time_in[HSR_PT_SLAVE_A]; +- time_b = node->time_in[HSR_PT_SLAVE_B]; +- +- /* Check for timestamps old enough to +- * risk wrap-around +- */ +- if (time_after(jiffies, time_a + MAX_JIFFY_OFFSET / 2)) +- node->time_in_stale[HSR_PT_SLAVE_A] = true; +- if (time_after(jiffies, time_b + MAX_JIFFY_OFFSET / 2)) +- node->time_in_stale[HSR_PT_SLAVE_B] = true; +- +- /* Get age of newest frame from node. +- * At least one time_in is OK here; nodes get pruned +- * long before both time_ins can get stale +- */ +- timestamp = time_a; +- if (node->time_in_stale[HSR_PT_SLAVE_A] || +- (!node->time_in_stale[HSR_PT_SLAVE_B] && +- time_after(time_b, time_a))) +- timestamp = time_b; +- +- /* Warn of ring error only as long as we get +- * frames at all +- */ +- if (time_is_after_jiffies(timestamp + +- msecs_to_jiffies(1.5 * MAX_SLAVE_DIFF))) { +- rcu_read_lock(); +- port = get_late_port(hsr, node); +- if (port) +- hsr_nl_ringerror(hsr, +- node->macaddress_A, +- port); +- rcu_read_unlock(); +- } +- +- /* Prune old entries */ +- if (time_is_before_jiffies(timestamp + +- msecs_to_jiffies(HSR_NODE_FORGET_TIME))) { +- hsr_nl_nodedown(hsr, node->macaddress_A); +- hlist_del_rcu(&node->mac_list); +- /* Note that we need to free this +- * entry later: +- */ ++ /* Prune old entries */ ++ if (time_is_before_jiffies(timestamp + ++ msecs_to_jiffies(HSR_NODE_FORGET_TIME))) { ++ hsr_nl_nodedown(hsr, node->macaddress_A); ++ if (!node->removed) { ++ list_del_rcu(&node->mac_list); ++ node->removed = true; ++ /* Note that we need to free this entry later: */ + kfree_rcu(node, rcu_head); + } + } +@@ -600,20 +568,17 @@ void *hsr_get_next_node(struct hsr_priv *hsr, void *_pos, + unsigned char addr[ETH_ALEN]) + { + struct hsr_node *node; +- u32 hash; +- +- hash = hsr_mac_hash(hsr, addr); + + if (!_pos) { +- node = hsr_node_get_first(&hsr->node_db[hash], +- &hsr->list_lock); ++ node = list_first_or_null_rcu(&hsr->node_db, ++ struct hsr_node, mac_list); + if (node) + ether_addr_copy(addr, node->macaddress_A); + return node; + } + + node = _pos; +- hlist_for_each_entry_continue_rcu(node, mac_list) { ++ list_for_each_entry_continue_rcu(node, &hsr->node_db, mac_list) { + ether_addr_copy(addr, node->macaddress_A); + return node; + } +@@ -633,11 +598,8 @@ int hsr_get_node_data(struct hsr_priv *hsr, + struct hsr_node *node; + struct hsr_port *port; + unsigned long tdiff; +- u32 hash; +- +- hash = hsr_mac_hash(hsr, addr); + +- node = find_node_by_addr_A(&hsr->node_db[hash], addr); ++ node = find_node_by_addr_A(&hsr->node_db, addr); + if (!node) + return -ENOENT; + +diff --git a/net/hsr/hsr_framereg.h b/net/hsr/hsr_framereg.h +index f3762e9e42b54..b23556251d621 100644 +--- a/net/hsr/hsr_framereg.h ++++ b/net/hsr/hsr_framereg.h +@@ -28,17 +28,9 @@ struct hsr_frame_info { + bool is_from_san; + }; + +-#ifdef CONFIG_LOCKDEP +-int lockdep_hsr_is_held(spinlock_t *lock); +-#else +-#define lockdep_hsr_is_held(lock) 1 +-#endif +- +-u32 hsr_mac_hash(struct hsr_priv *hsr, const unsigned char *addr); +-struct hsr_node *hsr_node_get_first(struct hlist_head *head, spinlock_t *lock); + void hsr_del_self_node(struct hsr_priv *hsr); +-void hsr_del_nodes(struct hlist_head *node_db); +-struct hsr_node *hsr_get_node(struct hsr_port *port, struct hlist_head *node_db, ++void hsr_del_nodes(struct list_head *node_db); ++struct hsr_node *hsr_get_node(struct hsr_port *port, struct list_head *node_db, + struct sk_buff *skb, bool is_sup, + enum hsr_port_type rx_port); + void hsr_handle_sup_frame(struct hsr_frame_info *frame); +@@ -76,7 +68,9 @@ void prp_handle_san_frame(bool san, enum hsr_port_type port, + void prp_update_san_info(struct hsr_node *node, bool is_sup); + + struct hsr_node { +- struct hlist_node mac_list; ++ struct list_head mac_list; ++ /* Protect R/W access to seq_out */ ++ spinlock_t seq_out_lock; + unsigned char macaddress_A[ETH_ALEN]; + unsigned char macaddress_B[ETH_ALEN]; + /* Local slave through which AddrB frames are received from this node */ +@@ -88,6 +82,7 @@ struct hsr_node { + bool san_a; + bool san_b; + u16 seq_out[HSR_PT_PORTS]; ++ bool removed; + struct rcu_head rcu_head; + }; + +diff --git a/net/hsr/hsr_main.h b/net/hsr/hsr_main.h +index b158ba409f9a4..16ae9fb09ccd2 100644 +--- a/net/hsr/hsr_main.h ++++ b/net/hsr/hsr_main.h +@@ -47,9 +47,6 @@ + + #define HSR_V1_SUP_LSDUSIZE 52 + +-#define HSR_HSIZE_SHIFT 8 +-#define HSR_HSIZE BIT(HSR_HSIZE_SHIFT) +- + /* The helper functions below assumes that 'path' occupies the 4 most + * significant bits of the 16-bit field shared by 'path' and 'LSDU_size' (or + * equivalently, the 4 most significant bits of HSR tag byte 14). +@@ -188,8 +185,8 @@ struct hsr_proto_ops { + struct hsr_priv { + struct rcu_head rcu_head; + struct list_head ports; +- struct hlist_head node_db[HSR_HSIZE]; /* Known HSR nodes */ +- struct hlist_head self_node_db; /* MACs of slaves */ ++ struct list_head node_db; /* Known HSR nodes */ ++ struct list_head self_node_db; /* MACs of slaves */ + struct timer_list announce_timer; /* Supervision frame dispatch */ + struct timer_list prune_timer; + int announce_count; +@@ -199,8 +196,6 @@ struct hsr_priv { + spinlock_t seqnr_lock; /* locking for sequence_nr */ + spinlock_t list_lock; /* locking for node list */ + struct hsr_proto_ops *proto_ops; +- u32 hash_buckets; +- u32 hash_seed; + #define PRP_LAN_ID 0x5 /* 0x1010 for A and 0x1011 for B. Bit 0 is set + * based on SLAVE_A or SLAVE_B + */ +diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c +index 7174a90929002..78fe40eb9f012 100644 +--- a/net/hsr/hsr_netlink.c ++++ b/net/hsr/hsr_netlink.c +@@ -105,7 +105,6 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev, + static void hsr_dellink(struct net_device *dev, struct list_head *head) + { + struct hsr_priv *hsr = netdev_priv(dev); +- int i; + + del_timer_sync(&hsr->prune_timer); + del_timer_sync(&hsr->announce_timer); +@@ -114,8 +113,7 @@ static void hsr_dellink(struct net_device *dev, struct list_head *head) + hsr_del_ports(hsr); + + hsr_del_self_node(hsr); +- for (i = 0; i < hsr->hash_buckets; i++) +- hsr_del_nodes(&hsr->node_db[i]); ++ hsr_del_nodes(&hsr->node_db); + + unregister_netdevice_queue(dev, head); + } +diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c +index 0da6794113308..92d4237862518 100644 +--- a/net/ipv4/af_inet.c ++++ b/net/ipv4/af_inet.c +@@ -522,9 +522,9 @@ int __inet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len, + /* Make sure we are allowed to bind here. */ + if (snum || !(inet->bind_address_no_port || + (flags & BIND_FORCE_ADDRESS_NO_PORT))) { +- if (sk->sk_prot->get_port(sk, snum)) { ++ err = sk->sk_prot->get_port(sk, snum); ++ if (err) { + inet->inet_saddr = inet->inet_rcv_saddr = 0; +- err = -EADDRINUSE; + goto out_release_sock; + } + if (!(flags & BIND_FROM_BPF)) { +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index 4e84ed21d16fe..4a34bc7cb15ed 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -471,11 +471,11 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum) + bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN; + bool found_port = false, check_bind_conflict = true; + bool bhash_created = false, bhash2_created = false; ++ int ret = -EADDRINUSE, port = snum, l3mdev; + struct inet_bind_hashbucket *head, *head2; + struct inet_bind2_bucket *tb2 = NULL; + struct inet_bind_bucket *tb = NULL; + bool head2_lock_acquired = false; +- int ret = 1, port = snum, l3mdev; + struct net *net = sock_net(sk); + + l3mdev = inet_sk_bound_l3mdev(sk); +@@ -1186,7 +1186,7 @@ int inet_csk_listen_start(struct sock *sk) + { + struct inet_connection_sock *icsk = inet_csk(sk); + struct inet_sock *inet = inet_sk(sk); +- int err = -EADDRINUSE; ++ int err; + + reqsk_queue_alloc(&icsk->icsk_accept_queue); + +@@ -1202,7 +1202,8 @@ int inet_csk_listen_start(struct sock *sk) + * after validation is complete. + */ + inet_sk_state_store(sk, TCP_LISTEN); +- if (!sk->sk_prot->get_port(sk, inet->inet_num)) { ++ err = sk->sk_prot->get_port(sk, inet->inet_num); ++ if (!err) { + inet->inet_sport = htons(inet->inet_num); + + sk_dst_reset(sk); +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index 04b4ec07bb06c..409ec2a1f95b0 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -143,7 +143,7 @@ next_port: + + fail: + spin_unlock(&ping_table.lock); +- return 1; ++ return -EADDRINUSE; + } + EXPORT_SYMBOL_GPL(ping_get_port); + +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index cf9c3e8f7ccbf..94aad3870c5fc 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -45,8 +45,11 @@ static int bpf_tcp_ingress(struct sock *sk, struct sk_psock *psock, + tmp->sg.end = i; + if (apply) { + apply_bytes -= size; +- if (!apply_bytes) ++ if (!apply_bytes) { ++ if (sge->length) ++ sk_msg_iter_var_prev(i); + break; ++ } + } + } while (i != msg->sg.end); + +@@ -131,10 +134,9 @@ static int tcp_bpf_push_locked(struct sock *sk, struct sk_msg *msg, + return ret; + } + +-int tcp_bpf_sendmsg_redir(struct sock *sk, struct sk_msg *msg, +- u32 bytes, int flags) ++int tcp_bpf_sendmsg_redir(struct sock *sk, bool ingress, ++ struct sk_msg *msg, u32 bytes, int flags) + { +- bool ingress = sk_msg_to_ingress(msg); + struct sk_psock *psock = sk_psock_get(sk); + int ret; + +@@ -276,10 +278,10 @@ msg_bytes_ready: + static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock, + struct sk_msg *msg, int *copied, int flags) + { +- bool cork = false, enospc = sk_msg_full(msg); ++ bool cork = false, enospc = sk_msg_full(msg), redir_ingress; + struct sock *sk_redir; + u32 tosend, origsize, sent, delta = 0; +- u32 eval = __SK_NONE; ++ u32 eval; + int ret; + + more_data: +@@ -310,6 +312,7 @@ more_data: + tosend = msg->sg.size; + if (psock->apply_bytes && psock->apply_bytes < tosend) + tosend = psock->apply_bytes; ++ eval = __SK_NONE; + + switch (psock->eval) { + case __SK_PASS: +@@ -321,6 +324,7 @@ more_data: + sk_msg_apply_bytes(psock, tosend); + break; + case __SK_REDIRECT: ++ redir_ingress = psock->redir_ingress; + sk_redir = psock->sk_redir; + sk_msg_apply_bytes(psock, tosend); + if (!psock->apply_bytes) { +@@ -337,7 +341,8 @@ more_data: + release_sock(sk); + + origsize = msg->sg.size; +- ret = tcp_bpf_sendmsg_redir(sk_redir, msg, tosend, flags); ++ ret = tcp_bpf_sendmsg_redir(sk_redir, redir_ingress, ++ msg, tosend, flags); + sent = origsize - msg->sg.size; + + if (eval == __SK_REDIRECT) +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index 6a320a614e547..2eaf47e23b221 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -232,16 +232,16 @@ static int udp_reuseport_add_sock(struct sock *sk, struct udp_hslot *hslot) + int udp_lib_get_port(struct sock *sk, unsigned short snum, + unsigned int hash2_nulladdr) + { +- struct udp_hslot *hslot, *hslot2; + struct udp_table *udptable = sk->sk_prot->h.udp_table; +- int error = 1; ++ struct udp_hslot *hslot, *hslot2; + struct net *net = sock_net(sk); ++ int error = -EADDRINUSE; + + if (!snum) { ++ DECLARE_BITMAP(bitmap, PORTS_PER_CHAIN); ++ unsigned short first, last; + int low, high, remaining; + unsigned int rand; +- unsigned short first, last; +- DECLARE_BITMAP(bitmap, PORTS_PER_CHAIN); + + inet_get_local_port_range(net, &low, &high); + remaining = (high - low) + 1; +@@ -2518,10 +2518,13 @@ static struct sock *__udp4_lib_mcast_demux_lookup(struct net *net, + __be16 rmt_port, __be32 rmt_addr, + int dif, int sdif) + { +- struct sock *sk, *result; + unsigned short hnum = ntohs(loc_port); +- unsigned int slot = udp_hashfn(net, hnum, udp_table.mask); +- struct udp_hslot *hslot = &udp_table.hash[slot]; ++ struct sock *sk, *result; ++ struct udp_hslot *hslot; ++ unsigned int slot; ++ ++ slot = udp_hashfn(net, hnum, udp_table.mask); ++ hslot = &udp_table.hash[slot]; + + /* Do not bother scanning a too big list */ + if (hslot->count > 10) +@@ -2549,14 +2552,18 @@ static struct sock *__udp4_lib_demux_lookup(struct net *net, + __be16 rmt_port, __be32 rmt_addr, + int dif, int sdif) + { +- unsigned short hnum = ntohs(loc_port); +- unsigned int hash2 = ipv4_portaddr_hash(net, loc_addr, hnum); +- unsigned int slot2 = hash2 & udp_table.mask; +- struct udp_hslot *hslot2 = &udp_table.hash2[slot2]; + INET_ADDR_COOKIE(acookie, rmt_addr, loc_addr); +- const __portpair ports = INET_COMBINED_PORTS(rmt_port, hnum); ++ unsigned short hnum = ntohs(loc_port); ++ unsigned int hash2, slot2; ++ struct udp_hslot *hslot2; ++ __portpair ports; + struct sock *sk; + ++ hash2 = ipv4_portaddr_hash(net, loc_addr, hnum); ++ slot2 = hash2 & udp_table.mask; ++ hslot2 = &udp_table.hash2[slot2]; ++ ports = INET_COMBINED_PORTS(rmt_port, hnum); ++ + udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) { + if (inet_match(net, sk, acookie, ports, dif, sdif)) + return sk; +@@ -2957,10 +2964,10 @@ EXPORT_SYMBOL(udp_prot); + + static struct sock *udp_get_first(struct seq_file *seq, int start) + { +- struct sock *sk; +- struct udp_seq_afinfo *afinfo; + struct udp_iter_state *state = seq->private; + struct net *net = seq_file_net(seq); ++ struct udp_seq_afinfo *afinfo; ++ struct sock *sk; + + if (state->bpf_seq_afinfo) + afinfo = state->bpf_seq_afinfo; +@@ -2991,9 +2998,9 @@ found: + + static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk) + { +- struct udp_seq_afinfo *afinfo; + struct udp_iter_state *state = seq->private; + struct net *net = seq_file_net(seq); ++ struct udp_seq_afinfo *afinfo; + + if (state->bpf_seq_afinfo) + afinfo = state->bpf_seq_afinfo; +@@ -3049,8 +3056,8 @@ EXPORT_SYMBOL(udp_seq_next); + + void udp_seq_stop(struct seq_file *seq, void *v) + { +- struct udp_seq_afinfo *afinfo; + struct udp_iter_state *state = seq->private; ++ struct udp_seq_afinfo *afinfo; + + if (state->bpf_seq_afinfo) + afinfo = state->bpf_seq_afinfo; +diff --git a/net/ipv4/udp_tunnel_core.c b/net/ipv4/udp_tunnel_core.c +index 8242c8947340e..5f8104cf082d0 100644 +--- a/net/ipv4/udp_tunnel_core.c ++++ b/net/ipv4/udp_tunnel_core.c +@@ -176,6 +176,7 @@ EXPORT_SYMBOL_GPL(udp_tunnel_xmit_skb); + void udp_tunnel_sock_release(struct socket *sock) + { + rcu_assign_sk_user_data(sock->sk, NULL); ++ synchronize_rcu(); + kernel_sock_shutdown(sock, SHUT_RDWR); + sock_release(sock); + } +diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c +index 0241910049825..7b0cd54da452b 100644 +--- a/net/ipv6/af_inet6.c ++++ b/net/ipv6/af_inet6.c +@@ -409,10 +409,10 @@ static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len, + /* Make sure we are allowed to bind here. */ + if (snum || !(inet->bind_address_no_port || + (flags & BIND_FORCE_ADDRESS_NO_PORT))) { +- if (sk->sk_prot->get_port(sk, snum)) { ++ err = sk->sk_prot->get_port(sk, snum); ++ if (err) { + sk->sk_ipv6only = saved_ipv6only; + inet_reset_saddr(sk); +- err = -EADDRINUSE; + goto out; + } + if (!(flags & BIND_FROM_BPF)) { +diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c +index 5ecb56522f9d6..ba28aeb7cade0 100644 +--- a/net/ipv6/datagram.c ++++ b/net/ipv6/datagram.c +@@ -42,24 +42,29 @@ static void ip6_datagram_flow_key_init(struct flowi6 *fl6, struct sock *sk) + { + struct inet_sock *inet = inet_sk(sk); + struct ipv6_pinfo *np = inet6_sk(sk); ++ int oif = sk->sk_bound_dev_if; + + memset(fl6, 0, sizeof(*fl6)); + fl6->flowi6_proto = sk->sk_protocol; + fl6->daddr = sk->sk_v6_daddr; + fl6->saddr = np->saddr; +- fl6->flowi6_oif = sk->sk_bound_dev_if; + fl6->flowi6_mark = sk->sk_mark; + fl6->fl6_dport = inet->inet_dport; + fl6->fl6_sport = inet->inet_sport; + fl6->flowlabel = np->flow_label; + fl6->flowi6_uid = sk->sk_uid; + +- if (!fl6->flowi6_oif) +- fl6->flowi6_oif = np->sticky_pktinfo.ipi6_ifindex; ++ if (!oif) ++ oif = np->sticky_pktinfo.ipi6_ifindex; + +- if (!fl6->flowi6_oif && ipv6_addr_is_multicast(&fl6->daddr)) +- fl6->flowi6_oif = np->mcast_oif; ++ if (!oif) { ++ if (ipv6_addr_is_multicast(&fl6->daddr)) ++ oif = np->mcast_oif; ++ else ++ oif = np->ucast_oif; ++ } + ++ fl6->flowi6_oif = oif; + security_sk_classify_flow(sk, flowi6_to_flowi_common(fl6)); + } + +diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c +index 5703d3cbea9ba..70d81bba50939 100644 +--- a/net/ipv6/sit.c ++++ b/net/ipv6/sit.c +@@ -694,7 +694,7 @@ static int ipip6_rcv(struct sk_buff *skb) + skb->dev = tunnel->dev; + + if (packet_is_spoofed(skb, iph, tunnel)) { +- tunnel->dev->stats.rx_errors++; ++ DEV_STATS_INC(tunnel->dev, rx_errors); + goto out; + } + +@@ -714,8 +714,8 @@ static int ipip6_rcv(struct sk_buff *skb) + net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n", + &iph->saddr, iph->tos); + if (err > 1) { +- ++tunnel->dev->stats.rx_frame_errors; +- ++tunnel->dev->stats.rx_errors; ++ DEV_STATS_INC(tunnel->dev, rx_frame_errors); ++ DEV_STATS_INC(tunnel->dev, rx_errors); + goto out; + } + } +@@ -942,7 +942,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, + if (!rt) { + rt = ip_route_output_flow(tunnel->net, &fl4, NULL); + if (IS_ERR(rt)) { +- dev->stats.tx_carrier_errors++; ++ DEV_STATS_INC(dev, tx_carrier_errors); + goto tx_error_icmp; + } + dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst, fl4.saddr); +@@ -950,14 +950,14 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, + + if (rt->rt_type != RTN_UNICAST && rt->rt_type != RTN_LOCAL) { + ip_rt_put(rt); +- dev->stats.tx_carrier_errors++; ++ DEV_STATS_INC(dev, tx_carrier_errors); + goto tx_error_icmp; + } + tdev = rt->dst.dev; + + if (tdev == dev) { + ip_rt_put(rt); +- dev->stats.collisions++; ++ DEV_STATS_INC(dev, collisions); + goto tx_error; + } + +@@ -970,7 +970,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, + mtu = dst_mtu(&rt->dst) - t_hlen; + + if (mtu < IPV4_MIN_MTU) { +- dev->stats.collisions++; ++ DEV_STATS_INC(dev, collisions); + ip_rt_put(rt); + goto tx_error; + } +@@ -1009,7 +1009,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, + struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); + if (!new_skb) { + ip_rt_put(rt); +- dev->stats.tx_dropped++; ++ DEV_STATS_INC(dev, tx_dropped); + kfree_skb(skb); + return NETDEV_TX_OK; + } +@@ -1039,7 +1039,7 @@ tx_error_icmp: + dst_link_failure(skb); + tx_error: + kfree_skb(skb); +- dev->stats.tx_errors++; ++ DEV_STATS_INC(dev, tx_errors); + return NETDEV_TX_OK; + } + +@@ -1058,7 +1058,7 @@ static netdev_tx_t sit_tunnel_xmit__(struct sk_buff *skb, + return NETDEV_TX_OK; + tx_error: + kfree_skb(skb); +- dev->stats.tx_errors++; ++ DEV_STATS_INC(dev, tx_errors); + return NETDEV_TX_OK; + } + +@@ -1087,7 +1087,7 @@ static netdev_tx_t sit_tunnel_xmit(struct sk_buff *skb, + return NETDEV_TX_OK; + + tx_err: +- dev->stats.tx_errors++; ++ DEV_STATS_INC(dev, tx_errors); + kfree_skb(skb); + return NETDEV_TX_OK; + +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index bc65e5b7195b3..98a64e8d9bdaa 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -1063,12 +1063,16 @@ static struct sock *__udp6_lib_demux_lookup(struct net *net, + int dif, int sdif) + { + unsigned short hnum = ntohs(loc_port); +- unsigned int hash2 = ipv6_portaddr_hash(net, loc_addr, hnum); +- unsigned int slot2 = hash2 & udp_table.mask; +- struct udp_hslot *hslot2 = &udp_table.hash2[slot2]; +- const __portpair ports = INET_COMBINED_PORTS(rmt_port, hnum); ++ unsigned int hash2, slot2; ++ struct udp_hslot *hslot2; ++ __portpair ports; + struct sock *sk; + ++ hash2 = ipv6_portaddr_hash(net, loc_addr, hnum); ++ slot2 = hash2 & udp_table.mask; ++ hslot2 = &udp_table.hash2[slot2]; ++ ports = INET_COMBINED_PORTS(rmt_port, hnum); ++ + udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) { + if (sk->sk_state == TCP_ESTABLISHED && + inet6_match(net, sk, rmt_addr, loc_addr, ports, dif, sdif)) +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index 687b4c878d4ad..8c8ef87997a8a 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -576,7 +576,7 @@ static struct ieee80211_key * + ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata, int link_id, + u8 key_idx, bool pairwise, const u8 *mac_addr) + { +- struct ieee80211_local *local = sdata->local; ++ struct ieee80211_local *local __maybe_unused = sdata->local; + struct ieee80211_link_data *link = &sdata->deflink; + struct ieee80211_key *key; + +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index a842f2e1c2309..de7b8a4d4bbbb 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -390,6 +390,7 @@ struct ieee80211_mgd_auth_data { + bool done, waiting; + bool peer_confirmed; + bool timeout_started; ++ int link_id; + + u8 ap_addr[ETH_ALEN] __aligned(2); + +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index dd9ac1f7d2ea6..46f08ec5ed760 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -2258,6 +2258,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, + + ret = cfg80211_register_netdevice(ndev); + if (ret) { ++ ieee80211_if_free(ndev); + free_netdev(ndev); + return ret; + } +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index d8484cd870de5..0125b3e6175b7 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -5033,6 +5033,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + struct cfg80211_rx_assoc_resp resp = { + .uapsd_queues = -1, + }; ++ u8 ap_mld_addr[ETH_ALEN] __aligned(2); + unsigned int link_id; + + sdata_assert_lock(sdata); +@@ -5199,6 +5200,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + resp.uapsd_queues |= ieee80211_ac_to_qos_mask[ac]; + } + ++ if (sdata->vif.valid_links) { ++ ether_addr_copy(ap_mld_addr, sdata->vif.cfg.ap_addr); ++ resp.ap_mld_addr = ap_mld_addr; ++ } ++ + ieee80211_destroy_assoc_data(sdata, + status_code == WLAN_STATUS_SUCCESS ? + ASSOC_SUCCESS : +@@ -5208,8 +5214,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + resp.len = len; + resp.req_ies = ifmgd->assoc_req_ies; + resp.req_ies_len = ifmgd->assoc_req_ies_len; +- if (sdata->vif.valid_links) +- resp.ap_mld_addr = sdata->vif.cfg.ap_addr; + cfg80211_rx_assoc_resp(sdata->dev, &resp); + notify_driver: + drv_mgd_complete_tx(sdata->local, sdata, &info); +@@ -6640,6 +6644,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, + req->ap_mld_addr ?: req->bss->bssid, + ETH_ALEN); + auth_data->bss = req->bss; ++ auth_data->link_id = req->link_id; + + if (req->auth_data_len >= 4) { + if (req->auth_type == NL80211_AUTHTYPE_SAE) { +@@ -6658,7 +6663,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, + * removal and re-addition of the STA entry in + * ieee80211_prep_connection(). + */ +- cont_auth = ifmgd->auth_data && req->bss == ifmgd->auth_data->bss; ++ cont_auth = ifmgd->auth_data && req->bss == ifmgd->auth_data->bss && ++ ifmgd->auth_data->link_id == req->link_id; + + if (req->ie && req->ie_len) { + memcpy(&auth_data->data[auth_data->data_len], +@@ -6982,7 +6988,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, + + /* keep sta info, bssid if matching */ + match = ether_addr_equal(ifmgd->auth_data->ap_addr, +- assoc_data->ap_addr); ++ assoc_data->ap_addr) && ++ ifmgd->auth_data->link_id == req->link_id; + ieee80211_destroy_auth_data(sdata, match); + } + +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index 874f2a4d831d0..cc10ee1ff8e93 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -2973,7 +2973,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, + + if (pre_conf_link_id != link_id && + link_id != IEEE80211_LINK_UNSPECIFIED) { +-#ifdef CPTCFG_MAC80211_VERBOSE_DEBUG ++#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + net_info_ratelimited("%s: dropped frame to %pM with bad link ID request (%d vs. %d)\n", + sdata->name, hdr.addr1, + pre_conf_link_id, link_id); +diff --git a/net/mctp/device.c b/net/mctp/device.c +index 99a3bda8852f8..acb97b2574289 100644 +--- a/net/mctp/device.c ++++ b/net/mctp/device.c +@@ -429,12 +429,6 @@ static void mctp_unregister(struct net_device *dev) + struct mctp_dev *mdev; + + mdev = mctp_dev_get_rtnl(dev); +- if (mdev && !mctp_known(dev)) { +- // Sanity check, should match what was set in mctp_register +- netdev_warn(dev, "%s: BUG mctp_ptr set for unknown type %d", +- __func__, dev->type); +- return; +- } + if (!mdev) + return; + +@@ -451,14 +445,8 @@ static int mctp_register(struct net_device *dev) + struct mctp_dev *mdev; + + /* Already registered? */ +- mdev = rtnl_dereference(dev->mctp_ptr); +- +- if (mdev) { +- if (!mctp_known(dev)) +- netdev_warn(dev, "%s: BUG mctp_ptr set for unknown type %d", +- __func__, dev->type); ++ if (rtnl_dereference(dev->mctp_ptr)) + return 0; +- } + + /* only register specific types */ + if (!mctp_known(dev)) +diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c +index 51ad557a525b5..b5ae419661b80 100644 +--- a/net/netfilter/ipvs/ip_vs_core.c ++++ b/net/netfilter/ipvs/ip_vs_core.c +@@ -132,21 +132,21 @@ ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb) + + s = this_cpu_ptr(dest->stats.cpustats); + u64_stats_update_begin(&s->syncp); +- s->cnt.inpkts++; +- s->cnt.inbytes += skb->len; ++ u64_stats_inc(&s->cnt.inpkts); ++ u64_stats_add(&s->cnt.inbytes, skb->len); + u64_stats_update_end(&s->syncp); + + svc = rcu_dereference(dest->svc); + s = this_cpu_ptr(svc->stats.cpustats); + u64_stats_update_begin(&s->syncp); +- s->cnt.inpkts++; +- s->cnt.inbytes += skb->len; ++ u64_stats_inc(&s->cnt.inpkts); ++ u64_stats_add(&s->cnt.inbytes, skb->len); + u64_stats_update_end(&s->syncp); + + s = this_cpu_ptr(ipvs->tot_stats.cpustats); + u64_stats_update_begin(&s->syncp); +- s->cnt.inpkts++; +- s->cnt.inbytes += skb->len; ++ u64_stats_inc(&s->cnt.inpkts); ++ u64_stats_add(&s->cnt.inbytes, skb->len); + u64_stats_update_end(&s->syncp); + + local_bh_enable(); +@@ -168,21 +168,21 @@ ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb) + + s = this_cpu_ptr(dest->stats.cpustats); + u64_stats_update_begin(&s->syncp); +- s->cnt.outpkts++; +- s->cnt.outbytes += skb->len; ++ u64_stats_inc(&s->cnt.outpkts); ++ u64_stats_add(&s->cnt.outbytes, skb->len); + u64_stats_update_end(&s->syncp); + + svc = rcu_dereference(dest->svc); + s = this_cpu_ptr(svc->stats.cpustats); + u64_stats_update_begin(&s->syncp); +- s->cnt.outpkts++; +- s->cnt.outbytes += skb->len; ++ u64_stats_inc(&s->cnt.outpkts); ++ u64_stats_add(&s->cnt.outbytes, skb->len); + u64_stats_update_end(&s->syncp); + + s = this_cpu_ptr(ipvs->tot_stats.cpustats); + u64_stats_update_begin(&s->syncp); +- s->cnt.outpkts++; +- s->cnt.outbytes += skb->len; ++ u64_stats_inc(&s->cnt.outpkts); ++ u64_stats_add(&s->cnt.outbytes, skb->len); + u64_stats_update_end(&s->syncp); + + local_bh_enable(); +@@ -200,17 +200,17 @@ ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc) + + s = this_cpu_ptr(cp->dest->stats.cpustats); + u64_stats_update_begin(&s->syncp); +- s->cnt.conns++; ++ u64_stats_inc(&s->cnt.conns); + u64_stats_update_end(&s->syncp); + + s = this_cpu_ptr(svc->stats.cpustats); + u64_stats_update_begin(&s->syncp); +- s->cnt.conns++; ++ u64_stats_inc(&s->cnt.conns); + u64_stats_update_end(&s->syncp); + + s = this_cpu_ptr(ipvs->tot_stats.cpustats); + u64_stats_update_begin(&s->syncp); +- s->cnt.conns++; ++ u64_stats_inc(&s->cnt.conns); + u64_stats_update_end(&s->syncp); + + local_bh_enable(); +diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c +index 988222fff9f02..03af6a2ffd567 100644 +--- a/net/netfilter/ipvs/ip_vs_ctl.c ++++ b/net/netfilter/ipvs/ip_vs_ctl.c +@@ -2297,11 +2297,11 @@ static int ip_vs_stats_percpu_show(struct seq_file *seq, void *v) + + do { + start = u64_stats_fetch_begin_irq(&u->syncp); +- conns = u->cnt.conns; +- inpkts = u->cnt.inpkts; +- outpkts = u->cnt.outpkts; +- inbytes = u->cnt.inbytes; +- outbytes = u->cnt.outbytes; ++ conns = u64_stats_read(&u->cnt.conns); ++ inpkts = u64_stats_read(&u->cnt.inpkts); ++ outpkts = u64_stats_read(&u->cnt.outpkts); ++ inbytes = u64_stats_read(&u->cnt.inbytes); ++ outbytes = u64_stats_read(&u->cnt.outbytes); + } while (u64_stats_fetch_retry_irq(&u->syncp, start)); + + seq_printf(seq, "%3X %8LX %8LX %8LX %16LX %16LX\n", +diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c +index 9a1a7af6a186a..f53150d82a92d 100644 +--- a/net/netfilter/ipvs/ip_vs_est.c ++++ b/net/netfilter/ipvs/ip_vs_est.c +@@ -67,11 +67,11 @@ static void ip_vs_read_cpu_stats(struct ip_vs_kstats *sum, + if (add) { + do { + start = u64_stats_fetch_begin(&s->syncp); +- conns = s->cnt.conns; +- inpkts = s->cnt.inpkts; +- outpkts = s->cnt.outpkts; +- inbytes = s->cnt.inbytes; +- outbytes = s->cnt.outbytes; ++ conns = u64_stats_read(&s->cnt.conns); ++ inpkts = u64_stats_read(&s->cnt.inpkts); ++ outpkts = u64_stats_read(&s->cnt.outpkts); ++ inbytes = u64_stats_read(&s->cnt.inbytes); ++ outbytes = u64_stats_read(&s->cnt.outbytes); + } while (u64_stats_fetch_retry(&s->syncp, start)); + sum->conns += conns; + sum->inpkts += inpkts; +@@ -82,11 +82,11 @@ static void ip_vs_read_cpu_stats(struct ip_vs_kstats *sum, + add = true; + do { + start = u64_stats_fetch_begin(&s->syncp); +- sum->conns = s->cnt.conns; +- sum->inpkts = s->cnt.inpkts; +- sum->outpkts = s->cnt.outpkts; +- sum->inbytes = s->cnt.inbytes; +- sum->outbytes = s->cnt.outbytes; ++ sum->conns = u64_stats_read(&s->cnt.conns); ++ sum->inpkts = u64_stats_read(&s->cnt.inpkts); ++ sum->outpkts = u64_stats_read(&s->cnt.outpkts); ++ sum->inbytes = u64_stats_read(&s->cnt.inbytes); ++ sum->outbytes = u64_stats_read(&s->cnt.outbytes); + } while (u64_stats_fetch_retry(&s->syncp, start)); + } + } +diff --git a/net/netfilter/nf_conntrack_proto_icmpv6.c b/net/netfilter/nf_conntrack_proto_icmpv6.c +index 61e3b05cf02c3..1020d67600a95 100644 +--- a/net/netfilter/nf_conntrack_proto_icmpv6.c ++++ b/net/netfilter/nf_conntrack_proto_icmpv6.c +@@ -129,6 +129,56 @@ static void icmpv6_error_log(const struct sk_buff *skb, + nf_l4proto_log_invalid(skb, state, IPPROTO_ICMPV6, "%s", msg); + } + ++static noinline_for_stack int ++nf_conntrack_icmpv6_redirect(struct nf_conn *tmpl, struct sk_buff *skb, ++ unsigned int dataoff, ++ const struct nf_hook_state *state) ++{ ++ u8 hl = ipv6_hdr(skb)->hop_limit; ++ union nf_inet_addr outer_daddr; ++ union { ++ struct nd_opt_hdr nd_opt; ++ struct rd_msg rd_msg; ++ } tmp; ++ const struct nd_opt_hdr *nd_opt; ++ const struct rd_msg *rd_msg; ++ ++ rd_msg = skb_header_pointer(skb, dataoff, sizeof(*rd_msg), &tmp.rd_msg); ++ if (!rd_msg) { ++ icmpv6_error_log(skb, state, "short redirect"); ++ return -NF_ACCEPT; ++ } ++ ++ if (rd_msg->icmph.icmp6_code != 0) ++ return NF_ACCEPT; ++ ++ if (hl != 255 || !(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) { ++ icmpv6_error_log(skb, state, "invalid saddr or hoplimit for redirect"); ++ return -NF_ACCEPT; ++ } ++ ++ dataoff += sizeof(*rd_msg); ++ ++ /* warning: rd_msg no longer usable after this call */ ++ nd_opt = skb_header_pointer(skb, dataoff, sizeof(*nd_opt), &tmp.nd_opt); ++ if (!nd_opt || nd_opt->nd_opt_len == 0) { ++ icmpv6_error_log(skb, state, "redirect without options"); ++ return -NF_ACCEPT; ++ } ++ ++ /* We could call ndisc_parse_options(), but it would need ++ * skb_linearize() and a bit more work. ++ */ ++ if (nd_opt->nd_opt_type != ND_OPT_REDIRECT_HDR) ++ return NF_ACCEPT; ++ ++ memcpy(&outer_daddr.ip6, &ipv6_hdr(skb)->daddr, ++ sizeof(outer_daddr.ip6)); ++ dataoff += 8; ++ return nf_conntrack_inet_error(tmpl, skb, dataoff, state, ++ IPPROTO_ICMPV6, &outer_daddr); ++} ++ + int nf_conntrack_icmpv6_error(struct nf_conn *tmpl, + struct sk_buff *skb, + unsigned int dataoff, +@@ -159,6 +209,9 @@ int nf_conntrack_icmpv6_error(struct nf_conn *tmpl, + return NF_ACCEPT; + } + ++ if (icmp6h->icmp6_type == NDISC_REDIRECT) ++ return nf_conntrack_icmpv6_redirect(tmpl, skb, dataoff, state); ++ + /* is not error message ? */ + if (icmp6h->icmp6_type >= 128) + return NF_ACCEPT; +diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c +index 0fdcdb2c9ae43..4d9b99abe37d6 100644 +--- a/net/netfilter/nf_flow_table_offload.c ++++ b/net/netfilter/nf_flow_table_offload.c +@@ -383,12 +383,12 @@ static void flow_offload_ipv6_mangle(struct nf_flow_rule *flow_rule, + const __be32 *addr, const __be32 *mask) + { + struct flow_action_entry *entry; +- int i, j; ++ int i; + +- for (i = 0, j = 0; i < sizeof(struct in6_addr) / sizeof(u32); i += sizeof(u32), j++) { ++ for (i = 0; i < sizeof(struct in6_addr) / sizeof(u32); i++) { + entry = flow_action_entry_next(flow_rule); + flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP6, +- offset + i, &addr[j], mask); ++ offset + i * sizeof(u32), &addr[i], mask); + } + } + +diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c +index 8b84869eb2ac7..fa0f1952d7637 100644 +--- a/net/openvswitch/datapath.c ++++ b/net/openvswitch/datapath.c +@@ -948,6 +948,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) + struct sw_flow_mask mask; + struct sk_buff *reply; + struct datapath *dp; ++ struct sw_flow_key *key; + struct sw_flow_actions *acts; + struct sw_flow_match match; + u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]); +@@ -975,24 +976,26 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) + } + + /* Extract key. */ +- ovs_match_init(&match, &new_flow->key, false, &mask); ++ key = kzalloc(sizeof(*key), GFP_KERNEL); ++ if (!key) { ++ error = -ENOMEM; ++ goto err_kfree_key; ++ } ++ ++ ovs_match_init(&match, key, false, &mask); + error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY], + a[OVS_FLOW_ATTR_MASK], log); + if (error) + goto err_kfree_flow; + ++ ovs_flow_mask_key(&new_flow->key, key, true, &mask); ++ + /* Extract flow identifier. */ + error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID], +- &new_flow->key, log); ++ key, log); + if (error) + goto err_kfree_flow; + +- /* unmasked key is needed to match when ufid is not used. */ +- if (ovs_identifier_is_key(&new_flow->id)) +- match.key = new_flow->id.unmasked_key; +- +- ovs_flow_mask_key(&new_flow->key, &new_flow->key, true, &mask); +- + /* Validate actions. */ + error = ovs_nla_copy_actions(net, a[OVS_FLOW_ATTR_ACTIONS], + &new_flow->key, &acts, log); +@@ -1019,7 +1022,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) + if (ovs_identifier_is_ufid(&new_flow->id)) + flow = ovs_flow_tbl_lookup_ufid(&dp->table, &new_flow->id); + if (!flow) +- flow = ovs_flow_tbl_lookup(&dp->table, &new_flow->key); ++ flow = ovs_flow_tbl_lookup(&dp->table, key); + if (likely(!flow)) { + rcu_assign_pointer(new_flow->sf_acts, acts); + +@@ -1089,6 +1092,8 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) + + if (reply) + ovs_notify(&dp_flow_genl_family, reply, info); ++ ++ kfree(key); + return 0; + + err_unlock_ovs: +@@ -1098,6 +1103,8 @@ err_kfree_acts: + ovs_nla_free_flow_actions(acts); + err_kfree_flow: + ovs_flow_free(new_flow, false); ++err_kfree_key: ++ kfree(key); + error: + return error; + } +diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c +index 4a07ab094a84e..ead5418c126e3 100644 +--- a/net/openvswitch/flow_netlink.c ++++ b/net/openvswitch/flow_netlink.c +@@ -2309,7 +2309,7 @@ static struct sw_flow_actions *nla_alloc_flow_actions(int size) + + WARN_ON_ONCE(size > MAX_ACTIONS_BUFSIZE); + +- sfa = kmalloc(sizeof(*sfa) + size, GFP_KERNEL); ++ sfa = kmalloc(kmalloc_size_roundup(sizeof(*sfa) + size), GFP_KERNEL); + if (!sfa) + return ERR_PTR(-ENOMEM); + +diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c +index 9683617db7049..08c117bc083ec 100644 +--- a/net/rxrpc/output.c ++++ b/net/rxrpc/output.c +@@ -93,7 +93,7 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_connection *conn, + *_hard_ack = hard_ack; + *_top = top; + +- pkt->ack.bufferSpace = htons(8); ++ pkt->ack.bufferSpace = htons(0); + pkt->ack.maxSkew = htons(0); + pkt->ack.firstPacket = htonl(hard_ack + 1); + pkt->ack.previousPacket = htonl(call->ackr_highest_seq); +diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c +index 3c3a626459deb..d4e4e94f4f987 100644 +--- a/net/rxrpc/sendmsg.c ++++ b/net/rxrpc/sendmsg.c +@@ -716,7 +716,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len) + if (call->tx_total_len != -1 || + call->tx_pending || + call->tx_top != 0) +- goto error_put; ++ goto out_put_unlock; + call->tx_total_len = p.call.tx_total_len; + } + } +diff --git a/net/sched/ematch.c b/net/sched/ematch.c +index 4ce6813618515..5c1235e6076ae 100644 +--- a/net/sched/ematch.c ++++ b/net/sched/ematch.c +@@ -255,6 +255,8 @@ static int tcf_em_validate(struct tcf_proto *tp, + * the value carried. + */ + if (em_hdr->flags & TCF_EM_SIMPLE) { ++ if (em->ops->datalen > 0) ++ goto errout; + if (data_len < sizeof(u32)) + goto errout; + em->data = *(u32 *) data; +diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c +index b46a416787ec3..43ebf090029d7 100644 +--- a/net/sctp/sysctl.c ++++ b/net/sctp/sysctl.c +@@ -84,17 +84,18 @@ static struct ctl_table sctp_table[] = { + { /* sentinel */ } + }; + ++/* The following index defines are used in sctp_sysctl_net_register(). ++ * If you add new items to the sctp_net_table, please ensure that ++ * the index values of these defines hold the same meaning indicated by ++ * their macro names when they appear in sctp_net_table. ++ */ ++#define SCTP_RTO_MIN_IDX 0 ++#define SCTP_RTO_MAX_IDX 1 ++#define SCTP_PF_RETRANS_IDX 2 ++#define SCTP_PS_RETRANS_IDX 3 ++ + static struct ctl_table sctp_net_table[] = { +- { +- .procname = "rto_initial", +- .data = &init_net.sctp.rto_initial, +- .maxlen = sizeof(unsigned int), +- .mode = 0644, +- .proc_handler = proc_dointvec_minmax, +- .extra1 = SYSCTL_ONE, +- .extra2 = &timer_max +- }, +- { ++ [SCTP_RTO_MIN_IDX] = { + .procname = "rto_min", + .data = &init_net.sctp.rto_min, + .maxlen = sizeof(unsigned int), +@@ -103,7 +104,7 @@ static struct ctl_table sctp_net_table[] = { + .extra1 = SYSCTL_ONE, + .extra2 = &init_net.sctp.rto_max + }, +- { ++ [SCTP_RTO_MAX_IDX] = { + .procname = "rto_max", + .data = &init_net.sctp.rto_max, + .maxlen = sizeof(unsigned int), +@@ -112,6 +113,33 @@ static struct ctl_table sctp_net_table[] = { + .extra1 = &init_net.sctp.rto_min, + .extra2 = &timer_max + }, ++ [SCTP_PF_RETRANS_IDX] = { ++ .procname = "pf_retrans", ++ .data = &init_net.sctp.pf_retrans, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = SYSCTL_ZERO, ++ .extra2 = &init_net.sctp.ps_retrans, ++ }, ++ [SCTP_PS_RETRANS_IDX] = { ++ .procname = "ps_retrans", ++ .data = &init_net.sctp.ps_retrans, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = &init_net.sctp.pf_retrans, ++ .extra2 = &ps_retrans_max, ++ }, ++ { ++ .procname = "rto_initial", ++ .data = &init_net.sctp.rto_initial, ++ .maxlen = sizeof(unsigned int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = SYSCTL_ONE, ++ .extra2 = &timer_max ++ }, + { + .procname = "rto_alpha_exp_divisor", + .data = &init_net.sctp.rto_alpha, +@@ -207,24 +235,6 @@ static struct ctl_table sctp_net_table[] = { + .extra1 = SYSCTL_ONE, + .extra2 = SYSCTL_INT_MAX, + }, +- { +- .procname = "pf_retrans", +- .data = &init_net.sctp.pf_retrans, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = proc_dointvec_minmax, +- .extra1 = SYSCTL_ZERO, +- .extra2 = &init_net.sctp.ps_retrans, +- }, +- { +- .procname = "ps_retrans", +- .data = &init_net.sctp.ps_retrans, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = proc_dointvec_minmax, +- .extra1 = &init_net.sctp.pf_retrans, +- .extra2 = &ps_retrans_max, +- }, + { + .procname = "sndbuf_policy", + .data = &init_net.sctp.sndbuf_policy, +@@ -586,6 +596,11 @@ int sctp_sysctl_net_register(struct net *net) + for (i = 0; table[i].data; i++) + table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp; + ++ table[SCTP_RTO_MIN_IDX].extra2 = &net->sctp.rto_max; ++ table[SCTP_RTO_MAX_IDX].extra1 = &net->sctp.rto_min; ++ table[SCTP_PF_RETRANS_IDX].extra2 = &net->sctp.ps_retrans; ++ table[SCTP_PS_RETRANS_IDX].extra1 = &net->sctp.pf_retrans; ++ + net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table); + if (net->sctp.sysctl_header == NULL) { + kfree(table); +diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c +index bcd74dddbe2db..9a5db285d4ae5 100644 +--- a/net/sunrpc/auth_gss/svcauth_gss.c ++++ b/net/sunrpc/auth_gss/svcauth_gss.c +@@ -1162,18 +1162,23 @@ static int gss_read_proxy_verf(struct svc_rqst *rqstp, + return res; + + inlen = svc_getnl(argv); +- if (inlen > (argv->iov_len + rqstp->rq_arg.page_len)) ++ if (inlen > (argv->iov_len + rqstp->rq_arg.page_len)) { ++ kfree(in_handle->data); + return SVC_DENIED; ++ } + + pages = DIV_ROUND_UP(inlen, PAGE_SIZE); + in_token->pages = kcalloc(pages, sizeof(struct page *), GFP_KERNEL); +- if (!in_token->pages) ++ if (!in_token->pages) { ++ kfree(in_handle->data); + return SVC_DENIED; ++ } + in_token->page_base = 0; + in_token->page_len = inlen; + for (i = 0; i < pages; i++) { + in_token->pages[i] = alloc_page(GFP_KERNEL); + if (!in_token->pages[i]) { ++ kfree(in_handle->data); + gss_free_in_token_pages(in_token); + return SVC_DENIED; + } +diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c +index 993acf38af870..0b0b9f1eed469 100644 +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -1442,7 +1442,7 @@ static int rpc_sockname(struct net *net, struct sockaddr *sap, size_t salen, + break; + default: + err = -EAFNOSUPPORT; +- goto out; ++ goto out_release; + } + if (err < 0) { + dprintk("RPC: can't bind UDP socket (%d)\n", err); +diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c +index 44b87e4274b42..b098fde373abf 100644 +--- a/net/sunrpc/xprtrdma/verbs.c ++++ b/net/sunrpc/xprtrdma/verbs.c +@@ -831,7 +831,7 @@ struct rpcrdma_req *rpcrdma_req_create(struct rpcrdma_xprt *r_xprt, + return req; + + out3: +- kfree(req->rl_sendbuf); ++ rpcrdma_regbuf_free(req->rl_sendbuf); + out2: + kfree(req); + out1: +diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c +index 264cf367e2656..9ed9786341259 100644 +--- a/net/tls/tls_sw.c ++++ b/net/tls/tls_sw.c +@@ -792,7 +792,7 @@ static int bpf_exec_tx_verdict(struct sk_msg *msg, struct sock *sk, + struct sk_psock *psock; + struct sock *sk_redir; + struct tls_rec *rec; +- bool enospc, policy; ++ bool enospc, policy, redir_ingress; + int err = 0, send; + u32 delta = 0; + +@@ -837,6 +837,7 @@ more_data: + } + break; + case __SK_REDIRECT: ++ redir_ingress = psock->redir_ingress; + sk_redir = psock->sk_redir; + memcpy(&msg_redir, msg, sizeof(*msg)); + if (msg->apply_bytes < send) +@@ -846,7 +847,8 @@ more_data: + sk_msg_return_zero(sk, msg, send); + msg->sg.size -= send; + release_sock(sk); +- err = tcp_bpf_sendmsg_redir(sk_redir, &msg_redir, send, flags); ++ err = tcp_bpf_sendmsg_redir(sk_redir, redir_ingress, ++ &msg_redir, send, flags); + lock_sock(sk); + if (err < 0) { + *copied -= sk_msg_free_nocharge(sk, &msg_redir); +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index b3545fc680979..f0c2293f1d3b8 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1999,13 +1999,20 @@ restart_locked: + unix_state_lock(sk); + + err = 0; +- if (unix_peer(sk) == other) { ++ if (sk->sk_type == SOCK_SEQPACKET) { ++ /* We are here only when racing with unix_release_sock() ++ * is clearing @other. Never change state to TCP_CLOSE ++ * unlike SOCK_DGRAM wants. ++ */ ++ unix_state_unlock(sk); ++ err = -EPIPE; ++ } else if (unix_peer(sk) == other) { + unix_peer(sk) = NULL; + unix_dgram_peer_wake_disconnect_wakeup(sk, other); + ++ sk->sk_state = TCP_CLOSE; + unix_state_unlock(sk); + +- sk->sk_state = TCP_CLOSE; + unix_dgram_disconnected(sk, other); + sock_put(other); + err = -ECONNREFUSED; +@@ -3738,6 +3745,7 @@ static int __init af_unix_init(void) + rc = proto_register(&unix_stream_proto, 1); + if (rc != 0) { + pr_crit("%s: Cannot create unix_sock SLAB cache!\n", __func__); ++ proto_unregister(&unix_dgram_proto); + goto out; + } + +diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c +index 842c94286d316..36eb16a40745d 100644 +--- a/net/vmw_vsock/vmci_transport.c ++++ b/net/vmw_vsock/vmci_transport.c +@@ -1711,7 +1711,11 @@ static int vmci_transport_dgram_enqueue( + if (!dg) + return -ENOMEM; + +- memcpy_from_msg(VMCI_DG_PAYLOAD(dg), msg, len); ++ err = memcpy_from_msg(VMCI_DG_PAYLOAD(dg), msg, len); ++ if (err) { ++ kfree(dg); ++ return err; ++ } + + dg->dst = vmci_make_handle(remote_addr->svm_cid, + remote_addr->svm_port); +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 597c522365146..d2321c6833985 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -3868,6 +3868,9 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag + struct cfg80211_chan_def chandef = {}; + int ret; + ++ if (!link) ++ goto nla_put_failure; ++ + if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)) + goto nla_put_failure; + if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, +diff --git a/net/wireless/reg.c b/net/wireless/reg.c +index c3d950d294329..4f3f31244e8ba 100644 +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -4311,8 +4311,10 @@ static int __init regulatory_init_db(void) + return -EINVAL; + + err = load_builtin_regdb_keys(); +- if (err) ++ if (err) { ++ platform_device_unregister(reg_pdev); + return err; ++ } + + /* We always try to get an update for the static regdomain */ + err = regulatory_hint_core(cfg80211_world_regdom->alpha2); +diff --git a/samples/bpf/xdp1_user.c b/samples/bpf/xdp1_user.c +index ac370e638fa3d..281dc964de8da 100644 +--- a/samples/bpf/xdp1_user.c ++++ b/samples/bpf/xdp1_user.c +@@ -51,7 +51,7 @@ static void poll_stats(int map_fd, int interval) + + sleep(interval); + +- while (bpf_map_get_next_key(map_fd, &key, &key) != -1) { ++ while (bpf_map_get_next_key(map_fd, &key, &key) == 0) { + __u64 sum = 0; + + assert(bpf_map_lookup_elem(map_fd, &key, values) == 0); +diff --git a/samples/bpf/xdp2_kern.c b/samples/bpf/xdp2_kern.c +index 3332ba6bb95fb..67804ecf7ce37 100644 +--- a/samples/bpf/xdp2_kern.c ++++ b/samples/bpf/xdp2_kern.c +@@ -112,6 +112,10 @@ int xdp_prog1(struct xdp_md *ctx) + + if (ipproto == IPPROTO_UDP) { + swap_src_dst_mac(data); ++ ++ if (bpf_xdp_store_bytes(ctx, 0, pkt, sizeof(pkt))) ++ return rc; ++ + rc = XDP_TX; + } + +diff --git a/samples/vfio-mdev/mdpy-fb.c b/samples/vfio-mdev/mdpy-fb.c +index 9ec93d90e8a5a..4eb7aa11cfbb2 100644 +--- a/samples/vfio-mdev/mdpy-fb.c ++++ b/samples/vfio-mdev/mdpy-fb.c +@@ -109,7 +109,7 @@ static int mdpy_fb_probe(struct pci_dev *pdev, + + ret = pci_request_regions(pdev, "mdpy-fb"); + if (ret < 0) +- return ret; ++ goto err_disable_dev; + + pci_read_config_dword(pdev, MDPY_FORMAT_OFFSET, &format); + pci_read_config_dword(pdev, MDPY_WIDTH_OFFSET, &width); +@@ -191,6 +191,9 @@ err_release_fb: + err_release_regions: + pci_release_regions(pdev); + ++err_disable_dev: ++ pci_disable_device(pdev); ++ + return ret; + } + +@@ -199,7 +202,10 @@ static void mdpy_fb_remove(struct pci_dev *pdev) + struct fb_info *info = pci_get_drvdata(pdev); + + unregister_framebuffer(info); ++ iounmap(info->screen_base); + framebuffer_release(info); ++ pci_release_regions(pdev); ++ pci_disable_device(pdev); + } + + static struct pci_device_id mdpy_fb_pci_table[] = { +diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening +index d766b7d0ffd13..53baa95cb644f 100644 +--- a/security/Kconfig.hardening ++++ b/security/Kconfig.hardening +@@ -257,6 +257,9 @@ config INIT_ON_FREE_DEFAULT_ON + + config CC_HAS_ZERO_CALL_USED_REGS + def_bool $(cc-option,-fzero-call-used-regs=used-gpr) ++ # https://github.com/ClangBuiltLinux/linux/issues/1766 ++ # https://github.com/llvm/llvm-project/issues/59242 ++ depends on !CC_IS_CLANG || CLANG_VERSION > 150006 + + config ZERO_CALL_USED_REGS + bool "Enable register zeroing on function exit" +diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c +index d066ccc219e2d..7160e7aa58b94 100644 +--- a/security/apparmor/apparmorfs.c ++++ b/security/apparmor/apparmorfs.c +@@ -868,8 +868,10 @@ static struct multi_transaction *multi_transaction_new(struct file *file, + if (!t) + return ERR_PTR(-ENOMEM); + kref_init(&t->count); +- if (copy_from_user(t->data, buf, size)) ++ if (copy_from_user(t->data, buf, size)) { ++ put_multi_transaction(t); + return ERR_PTR(-EFAULT); ++ } + + return t; + } +diff --git a/security/apparmor/label.c b/security/apparmor/label.c +index 0f36ee9074381..a67c5897ee254 100644 +--- a/security/apparmor/label.c ++++ b/security/apparmor/label.c +@@ -197,15 +197,18 @@ static bool vec_is_stale(struct aa_profile **vec, int n) + return false; + } + +-static long union_vec_flags(struct aa_profile **vec, int n, long mask) ++static long accum_vec_flags(struct aa_profile **vec, int n) + { +- long u = 0; ++ long u = FLAG_UNCONFINED; + int i; + + AA_BUG(!vec); + + for (i = 0; i < n; i++) { +- u |= vec[i]->label.flags & mask; ++ u |= vec[i]->label.flags & (FLAG_DEBUG1 | FLAG_DEBUG2 | ++ FLAG_STALE); ++ if (!(u & vec[i]->label.flags & FLAG_UNCONFINED)) ++ u &= ~FLAG_UNCONFINED; + } + + return u; +@@ -1097,8 +1100,7 @@ static struct aa_label *label_merge_insert(struct aa_label *new, + else if (k == b->size) + return aa_get_label(b); + } +- new->flags |= union_vec_flags(new->vec, new->size, FLAG_UNCONFINED | +- FLAG_DEBUG1 | FLAG_DEBUG2); ++ new->flags |= accum_vec_flags(new->vec, new->size); + ls = labels_set(new); + write_lock_irqsave(&ls->lock, flags); + label = __label_insert(labels_set(new), new, false); +diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c +index f56070270c69d..1e2f40db15c58 100644 +--- a/security/apparmor/lsm.c ++++ b/security/apparmor/lsm.c +@@ -1194,10 +1194,10 @@ static int apparmor_inet_conn_request(const struct sock *sk, struct sk_buff *skb + #endif + + /* +- * The cred blob is a pointer to, not an instance of, an aa_task_ctx. ++ * The cred blob is a pointer to, not an instance of, an aa_label. + */ + struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = { +- .lbs_cred = sizeof(struct aa_task_ctx *), ++ .lbs_cred = sizeof(struct aa_label *), + .lbs_file = sizeof(struct aa_file_ctx), + .lbs_task = sizeof(struct aa_task_ctx), + }; +diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c +index 499c0209b6a46..fbdfcef91c616 100644 +--- a/security/apparmor/policy.c ++++ b/security/apparmor/policy.c +@@ -1170,7 +1170,7 @@ ssize_t aa_remove_profiles(struct aa_ns *policy_ns, struct aa_label *subj, + + if (!name) { + /* remove namespace - can only happen if fqname[0] == ':' */ +- mutex_lock_nested(&ns->parent->lock, ns->level); ++ mutex_lock_nested(&ns->parent->lock, ns->parent->level); + __aa_bump_ns_revision(ns); + __aa_remove_ns(ns); + mutex_unlock(&ns->parent->lock); +diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c +index 43beaad083feb..78700d94b4533 100644 +--- a/security/apparmor/policy_ns.c ++++ b/security/apparmor/policy_ns.c +@@ -134,7 +134,7 @@ static struct aa_ns *alloc_ns(const char *prefix, const char *name) + return ns; + + fail_unconfined: +- kfree_sensitive(ns->base.hname); ++ aa_policy_destroy(&ns->base); + fail_ns: + kfree_sensitive(ns); + return NULL; +diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c +index 55d31bac4f35b..9d26bbb901338 100644 +--- a/security/apparmor/policy_unpack.c ++++ b/security/apparmor/policy_unpack.c +@@ -972,7 +972,7 @@ static int verify_header(struct aa_ext *e, int required, const char **ns) + * if not specified use previous version + * Mask off everything that is not kernel abi version + */ +- if (VERSION_LT(e->version, v5) || VERSION_GT(e->version, v7)) { ++ if (VERSION_LT(e->version, v5) || VERSION_GT(e->version, v8)) { + audit_iface(NULL, NULL, NULL, "unsupported interface version", + e, error); + return error; +diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c +index 8a82a6c7f48a4..f2193c531f4a4 100644 +--- a/security/integrity/digsig.c ++++ b/security/integrity/digsig.c +@@ -126,6 +126,7 @@ int __init integrity_init_keyring(const unsigned int id) + { + struct key_restriction *restriction; + key_perm_t perm; ++ int ret; + + perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW + | KEY_USR_READ | KEY_USR_SEARCH; +@@ -154,7 +155,10 @@ int __init integrity_init_keyring(const unsigned int id) + perm |= KEY_USR_WRITE; + + out: +- return __integrity_init_keyring(id, perm, restriction); ++ ret = __integrity_init_keyring(id, perm, restriction); ++ if (ret) ++ kfree(restriction); ++ return ret; + } + + static int __init integrity_add_key(const unsigned int id, const void *data, +diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c +index a8802b8da946b..2edff7f58c25c 100644 +--- a/security/integrity/ima/ima_policy.c ++++ b/security/integrity/ima/ima_policy.c +@@ -398,12 +398,6 @@ static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry) + + nentry->lsm[i].type = entry->lsm[i].type; + nentry->lsm[i].args_p = entry->lsm[i].args_p; +- /* +- * Remove the reference from entry so that the associated +- * memory will not be freed during a later call to +- * ima_lsm_free_rule(entry). +- */ +- entry->lsm[i].args_p = NULL; + + ima_filter_rule_init(nentry->lsm[i].type, Audit_equal, + nentry->lsm[i].args_p, +@@ -417,6 +411,7 @@ static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry) + + static int ima_lsm_update_rule(struct ima_rule_entry *entry) + { ++ int i; + struct ima_rule_entry *nentry; + + nentry = ima_lsm_copy_rule(entry); +@@ -431,7 +426,8 @@ static int ima_lsm_update_rule(struct ima_rule_entry *entry) + * references and the entry itself. All other memory references will now + * be owned by nentry. + */ +- ima_lsm_free_rule(entry); ++ for (i = 0; i < MAX_LSM_RULES; i++) ++ ima_filter_rule_free(entry->lsm[i].rule); + kfree(entry); + + return 0; +@@ -549,6 +545,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule, + const char *func_data) + { + int i; ++ bool result = false; ++ struct ima_rule_entry *lsm_rule = rule; ++ bool rule_reinitialized = false; + + if ((rule->flags & IMA_FUNC) && + (rule->func != func && func != POST_SETATTR)) +@@ -610,35 +609,55 @@ static bool ima_match_rules(struct ima_rule_entry *rule, + int rc = 0; + u32 osid; + +- if (!rule->lsm[i].rule) { +- if (!rule->lsm[i].args_p) ++ if (!lsm_rule->lsm[i].rule) { ++ if (!lsm_rule->lsm[i].args_p) + continue; + else + return false; + } ++ ++retry: + switch (i) { + case LSM_OBJ_USER: + case LSM_OBJ_ROLE: + case LSM_OBJ_TYPE: + security_inode_getsecid(inode, &osid); +- rc = ima_filter_rule_match(osid, rule->lsm[i].type, ++ rc = ima_filter_rule_match(osid, lsm_rule->lsm[i].type, + Audit_equal, +- rule->lsm[i].rule); ++ lsm_rule->lsm[i].rule); + break; + case LSM_SUBJ_USER: + case LSM_SUBJ_ROLE: + case LSM_SUBJ_TYPE: +- rc = ima_filter_rule_match(secid, rule->lsm[i].type, ++ rc = ima_filter_rule_match(secid, lsm_rule->lsm[i].type, + Audit_equal, +- rule->lsm[i].rule); ++ lsm_rule->lsm[i].rule); + break; + default: + break; + } +- if (!rc) +- return false; ++ ++ if (rc == -ESTALE && !rule_reinitialized) { ++ lsm_rule = ima_lsm_copy_rule(rule); ++ if (lsm_rule) { ++ rule_reinitialized = true; ++ goto retry; ++ } ++ } ++ if (!rc) { ++ result = false; ++ goto out; ++ } + } +- return true; ++ result = true; ++ ++out: ++ if (rule_reinitialized) { ++ for (i = 0; i < MAX_LSM_RULES; i++) ++ ima_filter_rule_free(lsm_rule->lsm[i].rule); ++ kfree(lsm_rule); ++ } ++ return result; + } + + /* +diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c +index c25079faa2088..195ac18f09275 100644 +--- a/security/integrity/ima/ima_template.c ++++ b/security/integrity/ima/ima_template.c +@@ -245,11 +245,11 @@ int template_desc_init_fields(const char *template_fmt, + } + + if (fields && num_fields) { +- *fields = kmalloc_array(i, sizeof(*fields), GFP_KERNEL); ++ *fields = kmalloc_array(i, sizeof(**fields), GFP_KERNEL); + if (*fields == NULL) + return -ENOMEM; + +- memcpy(*fields, found_fields, i * sizeof(*fields)); ++ memcpy(*fields, found_fields, i * sizeof(**fields)); + *num_fields = i; + } + +diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c +index e05cfc2e49aeb..1e313982af02a 100644 +--- a/security/keys/encrypted-keys/encrypted.c ++++ b/security/keys/encrypted-keys/encrypted.c +@@ -627,7 +627,7 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key, + pr_err("encrypted key: instantiation of keys using provided decrypted data is disabled since CONFIG_USER_DECRYPTED_DATA is set to false\n"); + return ERR_PTR(-EINVAL); + } +- if (strlen(decrypted_data) != decrypted_datalen) { ++ if (strlen(decrypted_data) != decrypted_datalen * 2) { + pr_err("encrypted key: decrypted data provided does not match decrypted data length provided\n"); + return ERR_PTR(-EINVAL); + } +@@ -791,8 +791,8 @@ static int encrypted_init(struct encrypted_key_payload *epayload, + ret = encrypted_key_decrypt(epayload, format, hex_encoded_iv); + } else if (decrypted_data) { + get_random_bytes(epayload->iv, ivsize); +- memcpy(epayload->decrypted_data, decrypted_data, +- epayload->decrypted_datalen); ++ ret = hex2bin(epayload->decrypted_data, decrypted_data, ++ epayload->decrypted_datalen); + } else { + get_random_bytes(epayload->iv, ivsize); + get_random_bytes(epayload->decrypted_data, epayload->decrypted_datalen); +diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c +index de41621f4998e..110a5ab2b46bc 100644 +--- a/security/loadpin/loadpin.c ++++ b/security/loadpin/loadpin.c +@@ -122,21 +122,11 @@ static void loadpin_sb_free_security(struct super_block *mnt_sb) + } + } + +-static int loadpin_read_file(struct file *file, enum kernel_read_file_id id, +- bool contents) ++static int loadpin_check(struct file *file, enum kernel_read_file_id id) + { + struct super_block *load_root; + const char *origin = kernel_read_file_id_str(id); + +- /* +- * If we will not know that we'll be seeing the full contents +- * then we cannot trust a load will be complete and unchanged +- * off disk. Treat all contents=false hooks as if there were +- * no associated file struct. +- */ +- if (!contents) +- file = NULL; +- + /* If the file id is excluded, ignore the pinning. */ + if ((unsigned int)id < ARRAY_SIZE(ignore_read_file_id) && + ignore_read_file_id[id]) { +@@ -192,9 +182,25 @@ static int loadpin_read_file(struct file *file, enum kernel_read_file_id id, + return 0; + } + ++static int loadpin_read_file(struct file *file, enum kernel_read_file_id id, ++ bool contents) ++{ ++ /* ++ * LoadPin only cares about the _origin_ of a file, not its ++ * contents, so we can ignore the "are full contents available" ++ * argument here. ++ */ ++ return loadpin_check(file, id); ++} ++ + static int loadpin_load_data(enum kernel_load_data_id id, bool contents) + { +- return loadpin_read_file(NULL, (enum kernel_read_file_id) id, contents); ++ /* ++ * LoadPin only cares about the _origin_ of a file, not its ++ * contents, so a NULL file is passed, and we can ignore the ++ * state of "contents". ++ */ ++ return loadpin_check(NULL, (enum kernel_read_file_id) id); + } + + static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = { +diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c +index ba095558b6d16..7268304009ada 100644 +--- a/sound/core/memalloc.c ++++ b/sound/core/memalloc.c +@@ -720,7 +720,6 @@ static const struct snd_malloc_ops snd_dma_sg_wc_ops = { + struct snd_dma_sg_fallback { + size_t count; + struct page **pages; +- dma_addr_t *addrs; + }; + + static void __snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab, +@@ -732,38 +731,49 @@ static void __snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab, + for (i = 0; i < sgbuf->count && sgbuf->pages[i]; i++) + do_free_pages(page_address(sgbuf->pages[i]), PAGE_SIZE, wc); + kvfree(sgbuf->pages); +- kvfree(sgbuf->addrs); + kfree(sgbuf); + } + + static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size) + { + struct snd_dma_sg_fallback *sgbuf; +- struct page **pages; +- size_t i, count; ++ struct page **pagep, *curp; ++ size_t chunk, npages; ++ dma_addr_t addr; + void *p; + bool wc = dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK; + + sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL); + if (!sgbuf) + return NULL; +- count = PAGE_ALIGN(size) >> PAGE_SHIFT; +- pages = kvcalloc(count, sizeof(*pages), GFP_KERNEL); +- if (!pages) +- goto error; +- sgbuf->pages = pages; +- sgbuf->addrs = kvcalloc(count, sizeof(*sgbuf->addrs), GFP_KERNEL); +- if (!sgbuf->addrs) ++ size = PAGE_ALIGN(size); ++ sgbuf->count = size >> PAGE_SHIFT; ++ sgbuf->pages = kvcalloc(sgbuf->count, sizeof(*sgbuf->pages), GFP_KERNEL); ++ if (!sgbuf->pages) + goto error; + +- for (i = 0; i < count; sgbuf->count++, i++) { +- p = do_alloc_pages(dmab->dev.dev, PAGE_SIZE, &sgbuf->addrs[i], wc); +- if (!p) +- goto error; +- sgbuf->pages[i] = virt_to_page(p); ++ pagep = sgbuf->pages; ++ chunk = size; ++ while (size > 0) { ++ chunk = min(size, chunk); ++ p = do_alloc_pages(dmab->dev.dev, chunk, &addr, wc); ++ if (!p) { ++ if (chunk <= PAGE_SIZE) ++ goto error; ++ chunk >>= 1; ++ chunk = PAGE_SIZE << get_order(chunk); ++ continue; ++ } ++ ++ size -= chunk; ++ /* fill pages */ ++ npages = chunk >> PAGE_SHIFT; ++ curp = virt_to_page(p); ++ while (npages--) ++ *pagep++ = curp++; + } + +- p = vmap(pages, count, VM_MAP, PAGE_KERNEL); ++ p = vmap(sgbuf->pages, sgbuf->count, VM_MAP, PAGE_KERNEL); + if (!p) + goto error; + dmab->private_data = sgbuf; +diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c +index 33769ca78cc8f..9238abbfb2d62 100644 +--- a/sound/core/pcm_native.c ++++ b/sound/core/pcm_native.c +@@ -1432,8 +1432,10 @@ static int snd_pcm_do_start(struct snd_pcm_substream *substream, + static void snd_pcm_undo_start(struct snd_pcm_substream *substream, + snd_pcm_state_t state) + { +- if (substream->runtime->trigger_master == substream) ++ if (substream->runtime->trigger_master == substream) { + substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP); ++ substream->runtime->stop_operating = true; ++ } + } + + static void snd_pcm_post_start(struct snd_pcm_substream *substream, +diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c +index d3bc9e8c407dc..f0d34cf70c3e0 100644 +--- a/sound/drivers/mts64.c ++++ b/sound/drivers/mts64.c +@@ -815,6 +815,9 @@ static void snd_mts64_interrupt(void *private) + u8 status, data; + struct snd_rawmidi_substream *substream; + ++ if (!mts) ++ return; ++ + spin_lock(&mts->lock); + ret = mts64_read(mts->pardev->port); + data = ret & 0x00ff; +diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c +index bb31b7fe867d6..477a5b4b50bcb 100644 +--- a/sound/pci/asihpi/hpioctl.c ++++ b/sound/pci/asihpi/hpioctl.c +@@ -361,7 +361,7 @@ int asihpi_adapter_probe(struct pci_dev *pci_dev, + pci_dev->device, pci_dev->subsystem_vendor, + pci_dev->subsystem_device, pci_dev->devfn); + +- if (pci_enable_device(pci_dev) < 0) { ++ if (pcim_enable_device(pci_dev) < 0) { + dev_err(&pci_dev->dev, + "pci_enable_device failed, disabling device\n"); + return -EIO; +diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c +index b4d1e658c5560..edd653ece70d7 100644 +--- a/sound/pci/hda/hda_codec.c ++++ b/sound/pci/hda/hda_codec.c +@@ -2886,7 +2886,8 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec) + snd_hdac_enter_pm(&codec->core); + if (codec->patch_ops.suspend) + codec->patch_ops.suspend(codec); +- hda_cleanup_all_streams(codec); ++ if (!codec->no_stream_clean_at_suspend) ++ hda_cleanup_all_streams(codec); + state = hda_set_power_state(codec, AC_PWRST_D3); + update_power_acct(codec, true); + snd_hdac_leave_pm(&codec->core); +diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c +index 21edf7a619f07..386dd9d9143f9 100644 +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -167,6 +167,7 @@ struct hdmi_spec { + struct hdmi_ops ops; + + bool dyn_pin_out; ++ bool static_pcm_mapping; + /* hdmi interrupt trigger control flag for Nvidia codec */ + bool hdmi_intr_trig_ctrl; + bool nv_dp_workaround; /* workaround DP audio infoframe for Nvidia */ +@@ -1525,13 +1526,16 @@ static void update_eld(struct hda_codec *codec, + */ + pcm_jack = pin_idx_to_pcm_jack(codec, per_pin); + +- if (eld->eld_valid) { +- hdmi_attach_hda_pcm(spec, per_pin); +- hdmi_pcm_setup_pin(spec, per_pin); +- } else { +- hdmi_pcm_reset_pin(spec, per_pin); +- hdmi_detach_hda_pcm(spec, per_pin); ++ if (!spec->static_pcm_mapping) { ++ if (eld->eld_valid) { ++ hdmi_attach_hda_pcm(spec, per_pin); ++ hdmi_pcm_setup_pin(spec, per_pin); ++ } else { ++ hdmi_pcm_reset_pin(spec, per_pin); ++ hdmi_detach_hda_pcm(spec, per_pin); ++ } + } ++ + /* if pcm_idx == -1, it means this is in monitor connection event + * we can get the correct pcm_idx now. + */ +@@ -1738,6 +1742,7 @@ static void silent_stream_enable(struct hda_codec *codec, + + switch (spec->silent_stream_type) { + case SILENT_STREAM_KAE: ++ silent_stream_enable_i915(codec, per_pin); + silent_stream_set_kae(codec, per_pin, true); + break; + case SILENT_STREAM_I915: +@@ -1975,6 +1980,7 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) + static const struct snd_pci_quirk force_connect_list[] = { + SND_PCI_QUIRK(0x103c, 0x870f, "HP", 1), + SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1), ++ SND_PCI_QUIRK(0x103c, 0x8711, "HP", 1), + SND_PCI_QUIRK(0x1462, 0xec94, "MS-7C94", 1), + SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", 1), + {} +@@ -2279,8 +2285,8 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) + struct hdmi_spec *spec = codec->spec; + int idx, pcm_num; + +- /* limit the PCM devices to the codec converters */ +- pcm_num = spec->num_cvts; ++ /* limit the PCM devices to the codec converters or available PINs */ ++ pcm_num = min(spec->num_cvts, spec->num_pins); + codec_dbg(codec, "hdmi: pcm_num set to %d\n", pcm_num); + + for (idx = 0; idx < pcm_num; idx++) { +@@ -2377,6 +2383,11 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) + struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); + struct hdmi_eld *pin_eld = &per_pin->sink_eld; + ++ if (spec->static_pcm_mapping) { ++ hdmi_attach_hda_pcm(spec, per_pin); ++ hdmi_pcm_setup_pin(spec, per_pin); ++ } ++ + pin_eld->eld_valid = false; + hdmi_present_sense(per_pin, 0); + } +@@ -2878,9 +2889,33 @@ static int i915_hsw_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, + hda_nid_t pin_nid, int dev_id, u32 stream_tag, + int format) + { ++ struct hdmi_spec *spec = codec->spec; ++ int pin_idx = pin_id_to_pin_index(codec, pin_nid, dev_id); ++ struct hdmi_spec_per_pin *per_pin; ++ int res; ++ ++ if (pin_idx < 0) ++ per_pin = NULL; ++ else ++ per_pin = get_pin(spec, pin_idx); ++ + haswell_verify_D0(codec, cvt_nid, pin_nid); +- return hdmi_setup_stream(codec, cvt_nid, pin_nid, dev_id, +- stream_tag, format); ++ ++ if (spec->silent_stream_type == SILENT_STREAM_KAE && per_pin && per_pin->silent_stream) { ++ silent_stream_set_kae(codec, per_pin, false); ++ /* wait for pending transfers in codec to clear */ ++ usleep_range(100, 200); ++ } ++ ++ res = hdmi_setup_stream(codec, cvt_nid, pin_nid, dev_id, ++ stream_tag, format); ++ ++ if (spec->silent_stream_type == SILENT_STREAM_KAE && per_pin && per_pin->silent_stream) { ++ usleep_range(100, 200); ++ silent_stream_set_kae(codec, per_pin, true); ++ } ++ ++ return res; + } + + /* pin_cvt_fixup ops override for HSW+ and VLV+ */ +@@ -2900,6 +2935,88 @@ static void i915_pin_cvt_fixup(struct hda_codec *codec, + } + } + ++#ifdef CONFIG_PM ++static int i915_adlp_hdmi_suspend(struct hda_codec *codec) ++{ ++ struct hdmi_spec *spec = codec->spec; ++ bool silent_streams = false; ++ int pin_idx, res; ++ ++ res = generic_hdmi_suspend(codec); ++ ++ for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { ++ struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); ++ ++ if (per_pin->silent_stream) { ++ silent_streams = true; ++ break; ++ } ++ } ++ ++ if (silent_streams && spec->silent_stream_type == SILENT_STREAM_KAE) { ++ /* ++ * stream-id should remain programmed when codec goes ++ * to runtime suspend ++ */ ++ codec->no_stream_clean_at_suspend = 1; ++ ++ /* ++ * the system might go to S3, in which case keep-alive ++ * must be reprogrammed upon resume ++ */ ++ codec->forced_resume = 1; ++ ++ codec_dbg(codec, "HDMI: KAE active at suspend\n"); ++ } else { ++ codec->no_stream_clean_at_suspend = 0; ++ codec->forced_resume = 0; ++ } ++ ++ return res; ++} ++ ++static int i915_adlp_hdmi_resume(struct hda_codec *codec) ++{ ++ struct hdmi_spec *spec = codec->spec; ++ int pin_idx, res; ++ ++ res = generic_hdmi_resume(codec); ++ ++ /* KAE not programmed at suspend, nothing to do here */ ++ if (!codec->no_stream_clean_at_suspend) ++ return res; ++ ++ for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { ++ struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); ++ ++ /* ++ * If system was in suspend with monitor connected, ++ * the codec setting may have been lost. Re-enable ++ * keep-alive. ++ */ ++ if (per_pin->silent_stream) { ++ unsigned int param; ++ ++ param = snd_hda_codec_read(codec, per_pin->cvt_nid, 0, ++ AC_VERB_GET_CONV, 0); ++ if (!param) { ++ codec_dbg(codec, "HDMI: KAE: restore stream id\n"); ++ silent_stream_enable_i915(codec, per_pin); ++ } ++ ++ param = snd_hda_codec_read(codec, per_pin->cvt_nid, 0, ++ AC_VERB_GET_DIGI_CONVERT_1, 0); ++ if (!(param & (AC_DIG3_KAE << 16))) { ++ codec_dbg(codec, "HDMI: KAE: restore DIG3_KAE\n"); ++ silent_stream_set_kae(codec, per_pin, true); ++ } ++ } ++ } ++ ++ return res; ++} ++#endif ++ + /* precondition and allocation for Intel codecs */ + static int alloc_intel_hdmi(struct hda_codec *codec) + { +@@ -3030,8 +3147,14 @@ static int patch_i915_adlp_hdmi(struct hda_codec *codec) + if (!res) { + spec = codec->spec; + +- if (spec->silent_stream_type) ++ if (spec->silent_stream_type) { + spec->silent_stream_type = SILENT_STREAM_KAE; ++ ++#ifdef CONFIG_PM ++ codec->patch_ops.resume = i915_adlp_hdmi_resume; ++ codec->patch_ops.suspend = i915_adlp_hdmi_suspend; ++#endif ++ } + } + + return res; +@@ -4305,6 +4428,8 @@ static int patch_atihdmi(struct hda_codec *codec) + + spec = codec->spec; + ++ spec->static_pcm_mapping = true; ++ + spec->ops.pin_get_eld = atihdmi_pin_get_eld; + spec->ops.pin_setup_infoframe = atihdmi_pin_setup_infoframe; + spec->ops.pin_hbr_setup = atihdmi_pin_hbr_setup; +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index e5c0363856664..f5f640851fdcb 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -9354,6 +9354,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x8abb, "HP ZBook Firefly 14 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8ad1, "HP EliteBook 840 14 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8ad2, "HP EliteBook 860 16 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), ++ SND_PCI_QUIRK(0x103c, 0x8b5d, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), ++ SND_PCI_QUIRK(0x103c, 0x8b5e, "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), +@@ -10960,6 +10962,17 @@ static void alc897_fixup_lenovo_headset_mic(struct hda_codec *codec, + } + } + ++static void alc897_fixup_lenovo_headset_mode(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->parse_flags |= HDA_PINCFG_HEADSET_MIC; ++ 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), +@@ -11043,6 +11056,8 @@ enum { + ALC897_FIXUP_LENOVO_HEADSET_MIC, + ALC897_FIXUP_HEADSET_MIC_PIN, + ALC897_FIXUP_HP_HSMIC_VERB, ++ ALC897_FIXUP_LENOVO_HEADSET_MODE, ++ ALC897_FIXUP_HEADSET_MIC_PIN2, + }; + + static const struct hda_fixup alc662_fixups[] = { +@@ -11469,6 +11484,19 @@ static const struct hda_fixup alc662_fixups[] = { + { } + }, + }, ++ [ALC897_FIXUP_LENOVO_HEADSET_MODE] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc897_fixup_lenovo_headset_mode, ++ }, ++ [ALC897_FIXUP_HEADSET_MIC_PIN2] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x1a, 0x01a11140 }, /* use as headset mic, without its own jack detect */ ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC897_FIXUP_LENOVO_HEADSET_MODE ++ }, + }; + + static const struct snd_pci_quirk alc662_fixup_tbl[] = { +@@ -11521,6 +11549,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { + 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, 0x3742, "Lenovo TianYi510Pro-14IOB", ALC897_FIXUP_HEADSET_MIC_PIN2), + 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/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c +index 85a81add4ef9f..447612a7a7627 100644 +--- a/sound/soc/amd/acp/acp-platform.c ++++ b/sound/soc/amd/acp/acp-platform.c +@@ -184,10 +184,6 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs + + stream->substream = substream; + +- spin_lock_irq(&adata->acp_lock); +- list_add_tail(&stream->list, &adata->stream_list); +- spin_unlock_irq(&adata->acp_lock); +- + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + runtime->hw = acp_pcm_hardware_playback; + else +@@ -203,6 +199,10 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs + + writel(1, ACP_EXTERNAL_INTR_ENB(adata)); + ++ spin_lock_irq(&adata->acp_lock); ++ list_add_tail(&stream->list, &adata->stream_list); ++ spin_unlock_irq(&adata->acp_lock); ++ + return ret; + } + +diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c +index d9715bea965e1..1f0b5527c5949 100644 +--- a/sound/soc/amd/yc/acp6x-mach.c ++++ b/sound/soc/amd/yc/acp6x-mach.c +@@ -213,6 +213,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"), + } + }, ++ { ++ .driver_data = &acp6x_card, ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "TIMI"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Redmi Book Pro 14 2022"), ++ } ++ }, + {} + }; + +diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c +index 767463e82665c..89059a673cf09 100644 +--- a/sound/soc/codecs/pcm512x.c ++++ b/sound/soc/codecs/pcm512x.c +@@ -1634,7 +1634,7 @@ int pcm512x_probe(struct device *dev, struct regmap *regmap) + if (val > 6) { + dev_err(dev, "Invalid pll-in\n"); + ret = -EINVAL; +- goto err_clk; ++ goto err_pm; + } + pcm512x->pll_in = val; + } +@@ -1643,7 +1643,7 @@ int pcm512x_probe(struct device *dev, struct regmap *regmap) + if (val > 6) { + dev_err(dev, "Invalid pll-out\n"); + ret = -EINVAL; +- goto err_clk; ++ goto err_pm; + } + pcm512x->pll_out = val; + } +@@ -1652,12 +1652,12 @@ int pcm512x_probe(struct device *dev, struct regmap *regmap) + dev_err(dev, + "Error: both pll-in and pll-out, or none\n"); + ret = -EINVAL; +- goto err_clk; ++ goto err_pm; + } + if (pcm512x->pll_in && pcm512x->pll_in == pcm512x->pll_out) { + dev_err(dev, "Error: pll-in == pll-out\n"); + ret = -EINVAL; +- goto err_clk; ++ goto err_pm; + } + } + #endif +diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c +index a2ce52dafea84..cea26f3a02b6a 100644 +--- a/sound/soc/codecs/rt298.c ++++ b/sound/soc/codecs/rt298.c +@@ -1166,6 +1166,13 @@ static const struct dmi_system_id force_combo_jack_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "Geminilake") + } + }, ++ { ++ .ident = "Intel Kabylake R RVP", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Kabylake Client platform") ++ } ++ }, + { } + }; + +diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c +index ebac6caeb40ad..a230f441559a6 100644 +--- a/sound/soc/codecs/rt5670.c ++++ b/sound/soc/codecs/rt5670.c +@@ -3311,8 +3311,6 @@ static int rt5670_i2c_probe(struct i2c_client *i2c) + if (ret < 0) + goto err; + +- pm_runtime_put(&i2c->dev); +- + return 0; + err: + pm_runtime_disable(&i2c->dev); +diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c +index d3cfd3788f2ab..8fe9a75d12357 100644 +--- a/sound/soc/codecs/wm8994.c ++++ b/sound/soc/codecs/wm8994.c +@@ -3853,7 +3853,12 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data) + } else { + dev_dbg(component->dev, "Jack not detected\n"); + ++ /* Release wm8994->accdet_lock to avoid deadlock: ++ * cancel_delayed_work_sync() takes wm8994->mic_work internal ++ * lock and wm1811_mic_work takes wm8994->accdet_lock */ ++ mutex_unlock(&wm8994->accdet_lock); + cancel_delayed_work_sync(&wm8994->mic_work); ++ mutex_lock(&wm8994->accdet_lock); + + snd_soc_component_update_bits(component, WM8958_MICBIAS2, + WM8958_MICB2_DISCH, WM8958_MICB2_DISCH); +diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c +index c7b10bbfba7ea..0ddb6362fcc52 100644 +--- a/sound/soc/codecs/wsa883x.c ++++ b/sound/soc/codecs/wsa883x.c +@@ -7,7 +7,7 @@ + #include <linux/debugfs.h> + #include <linux/delay.h> + #include <linux/device.h> +-#include <linux/gpio.h> ++#include <linux/gpio/consumer.h> + #include <linux/init.h> + #include <linux/kernel.h> + #include <linux/module.h> +@@ -1392,7 +1392,7 @@ static int wsa883x_probe(struct sdw_slave *pdev, + } + + wsa883x->sd_n = devm_gpiod_get_optional(&pdev->dev, "powerdown", +- GPIOD_FLAGS_BIT_NONEXCLUSIVE); ++ GPIOD_FLAGS_BIT_NONEXCLUSIVE | GPIOD_OUT_HIGH); + if (IS_ERR(wsa883x->sd_n)) { + dev_err(&pdev->dev, "Shutdown Control GPIO not found\n"); + ret = PTR_ERR(wsa883x->sd_n); +@@ -1411,7 +1411,7 @@ static int wsa883x_probe(struct sdw_slave *pdev, + pdev->prop.simple_clk_stop_capable = true; + pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop; + pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; +- gpiod_direction_output(wsa883x->sd_n, 1); ++ gpiod_direction_output(wsa883x->sd_n, 0); + + wsa883x->regmap = devm_regmap_init_sdw(pdev, &wsa883x_regmap_config); + if (IS_ERR(wsa883x->regmap)) { +diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c +index fe7cf972d44ce..5daa824a4ffcf 100644 +--- a/sound/soc/generic/audio-graph-card.c ++++ b/sound/soc/generic/audio-graph-card.c +@@ -485,8 +485,10 @@ static int __graph_for_each_link(struct asoc_simple_priv *priv, + of_node_put(codec_ep); + of_node_put(codec_port); + +- if (ret < 0) ++ if (ret < 0) { ++ of_node_put(cpu_ep); + return ret; ++ } + + codec_port_old = codec_port; + } +diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig +index d2ca710ac3fa4..ac799de4f7fda 100644 +--- a/sound/soc/intel/Kconfig ++++ b/sound/soc/intel/Kconfig +@@ -177,7 +177,7 @@ config SND_SOC_INTEL_SKYLAKE_COMMON + select SND_HDA_DSP_LOADER + select SND_SOC_TOPOLOGY + select SND_SOC_INTEL_SST +- select SND_SOC_HDAC_HDA if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC ++ select SND_SOC_HDAC_HDA + select SND_SOC_ACPI_INTEL_MATCH + select SND_INTEL_DSP_CONFIG + help +diff --git a/sound/soc/intel/avs/boards/rt298.c b/sound/soc/intel/avs/boards/rt298.c +index b28d36872dcba..58c9d9edecf0a 100644 +--- a/sound/soc/intel/avs/boards/rt298.c ++++ b/sound/soc/intel/avs/boards/rt298.c +@@ -6,6 +6,7 @@ + // Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> + // + ++#include <linux/dmi.h> + #include <linux/module.h> + #include <sound/jack.h> + #include <sound/pcm.h> +@@ -14,6 +15,16 @@ + #include <sound/soc-acpi.h> + #include "../../../codecs/rt298.h" + ++static const struct dmi_system_id kblr_dmi_table[] = { ++ { ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), ++ DMI_MATCH(DMI_BOARD_NAME, "Kabylake R DDR4 RVP"), ++ }, ++ }, ++ {} ++}; ++ + static const struct snd_kcontrol_new card_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Mic Jack"), +@@ -96,9 +107,15 @@ avs_rt298_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_param + { + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); ++ unsigned int clk_freq; + int ret; + +- ret = snd_soc_dai_set_sysclk(codec_dai, RT298_SCLK_S_PLL, 19200000, SND_SOC_CLOCK_IN); ++ if (dmi_first_match(kblr_dmi_table)) ++ clk_freq = 24000000; ++ else ++ clk_freq = 19200000; ++ ++ ret = snd_soc_dai_set_sysclk(codec_dai, RT298_SCLK_S_PLL, clk_freq, SND_SOC_CLOCK_IN); + if (ret < 0) + dev_err(rtd->dev, "Set codec sysclk failed: %d\n", ret); + +@@ -139,7 +156,10 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in + dl->platforms = platform; + dl->num_platforms = 1; + dl->id = 0; +- dl->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; ++ if (dmi_first_match(kblr_dmi_table)) ++ dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; ++ else ++ dl->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->init = avs_rt298_codec_init; + dl->be_hw_params_fixup = avs_rt298_be_fixup; + dl->ops = &avs_rt298_ops; +diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c +index bb0719c58ca49..4f93639ce4887 100644 +--- a/sound/soc/intel/avs/core.c ++++ b/sound/soc/intel/avs/core.c +@@ -440,7 +440,7 @@ static int avs_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) + if (bus->mlcap) + snd_hdac_ext_bus_get_ml_capabilities(bus); + +- if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) ++ if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) + dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); + dma_set_max_seg_size(dev, UINT_MAX); + +diff --git a/sound/soc/intel/avs/ipc.c b/sound/soc/intel/avs/ipc.c +index 020d85c7520de..306f0dc4eaf58 100644 +--- a/sound/soc/intel/avs/ipc.c ++++ b/sound/soc/intel/avs/ipc.c +@@ -123,7 +123,10 @@ static void avs_dsp_recovery(struct avs_dev *adev) + if (!substream || !substream->runtime) + continue; + ++ /* No need for _irq() as we are in nonatomic context. */ ++ snd_pcm_stream_lock(substream); + snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED); ++ snd_pcm_stream_unlock(substream); + } + } + } +@@ -192,7 +195,8 @@ static void avs_dsp_receive_rx(struct avs_dev *adev, u64 header) + /* update size in case of LARGE_CONFIG_GET */ + if (msg.msg_target == AVS_MOD_MSG && + msg.global_msg_type == AVS_MOD_LARGE_CONFIG_GET) +- ipc->rx.size = msg.ext.large_config.data_off_size; ++ ipc->rx.size = min_t(u32, AVS_MAILBOX_SIZE, ++ msg.ext.large_config.data_off_size); + + memcpy_fromio(ipc->rx.data, avs_uplink_addr(adev), ipc->rx.size); + trace_avs_msg_payload(ipc->rx.data, ipc->rx.size); +diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c +index 70713e4b07dc1..773e5d1d87d46 100644 +--- a/sound/soc/intel/boards/sof_es8336.c ++++ b/sound/soc/intel/boards/sof_es8336.c +@@ -783,7 +783,7 @@ static int sof_es8336_remove(struct platform_device *pdev) + struct snd_soc_card *card = platform_get_drvdata(pdev); + struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card); + +- cancel_delayed_work(&priv->pcm_pop_work); ++ cancel_delayed_work_sync(&priv->pcm_pop_work); + gpiod_put(priv->gpio_speakers); + device_remove_software_node(priv->codec_dev); + put_device(priv->codec_dev); +diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c +index 3312b57e3c0cb..7f058acd221f0 100644 +--- a/sound/soc/intel/skylake/skl.c ++++ b/sound/soc/intel/skylake/skl.c +@@ -1116,7 +1116,10 @@ static void skl_shutdown(struct pci_dev *pci) + if (!skl->init_done) + return; + +- snd_hdac_stop_streams_and_chip(bus); ++ snd_hdac_stop_streams(bus); ++ snd_hdac_ext_bus_link_power_down_all(bus); ++ skl_dsp_sleep(skl->dsp); ++ + list_for_each_entry(s, &bus->stream_list, list) { + stream = stream_to_hdac_ext_stream(s); + snd_hdac_ext_stream_decouple(bus, stream, false); +diff --git a/sound/soc/mediatek/common/mtk-btcvsd.c b/sound/soc/mediatek/common/mtk-btcvsd.c +index d884bb7c0fc74..1c28b41e43112 100644 +--- a/sound/soc/mediatek/common/mtk-btcvsd.c ++++ b/sound/soc/mediatek/common/mtk-btcvsd.c +@@ -1038,11 +1038,9 @@ static int mtk_pcm_btcvsd_copy(struct snd_soc_component *component, + struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- mtk_btcvsd_snd_write(bt, buf, count); ++ return mtk_btcvsd_snd_write(bt, buf, count); + else +- mtk_btcvsd_snd_read(bt, buf, count); +- +- return 0; ++ return mtk_btcvsd_snd_read(bt, buf, count); + } + + /* kcontrol */ +diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +index dcaeeeb8aac70..bc155dd937e0b 100644 +--- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c ++++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +@@ -1070,16 +1070,6 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) + + afe->dev = &pdev->dev; + +- irq_id = platform_get_irq(pdev, 0); +- if (irq_id <= 0) +- return irq_id < 0 ? irq_id : -ENXIO; +- ret = devm_request_irq(afe->dev, irq_id, mt8173_afe_irq_handler, +- 0, "Afe_ISR_Handle", (void *)afe); +- if (ret) { +- dev_err(afe->dev, "could not request_irq\n"); +- return ret; +- } +- + afe->base_addr = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(afe->base_addr)) + return PTR_ERR(afe->base_addr); +@@ -1185,6 +1175,16 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) + if (ret) + goto err_cleanup_components; + ++ irq_id = platform_get_irq(pdev, 0); ++ if (irq_id <= 0) ++ return irq_id < 0 ? irq_id : -ENXIO; ++ ret = devm_request_irq(afe->dev, irq_id, mt8173_afe_irq_handler, ++ 0, "Afe_ISR_Handle", (void *)afe); ++ if (ret) { ++ dev_err(afe->dev, "could not request_irq\n"); ++ goto err_pm_disable; ++ } ++ + dev_info(&pdev->dev, "MT8173 AFE driver initialized.\n"); + return 0; + +diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c +index 12f40c81b101e..f803f121659de 100644 +--- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c ++++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c +@@ -200,14 +200,16 @@ static int mt8173_rt5650_rt5514_dev_probe(struct platform_device *pdev) + if (!mt8173_rt5650_rt5514_dais[DAI_LINK_CODEC_I2S].codecs[0].of_node) { + dev_err(&pdev->dev, + "Property 'audio-codec' missing or invalid\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto out; + } + mt8173_rt5650_rt5514_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node = + of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 1); + if (!mt8173_rt5650_rt5514_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node) { + dev_err(&pdev->dev, + "Property 'audio-codec' missing or invalid\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto out; + } + mt8173_rt5650_rt5514_codec_conf[0].dlc.of_node = + mt8173_rt5650_rt5514_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node; +@@ -216,6 +218,7 @@ static int mt8173_rt5650_rt5514_dev_probe(struct platform_device *pdev) + + ret = devm_snd_soc_register_card(&pdev->dev, card); + ++out: + of_node_put(platform_node); + return ret; + } +diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +index a860852236779..48c14be5e3db7 100644 +--- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c ++++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +@@ -677,8 +677,10 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) + } + + card = (struct snd_soc_card *)of_device_get_match_data(&pdev->dev); +- if (!card) ++ if (!card) { ++ of_node_put(platform_node); + return -EINVAL; ++ } + card->dev = &pdev->dev; + + ec_codec = of_parse_phandle(pdev->dev.of_node, "mediatek,ec-codec", 0); +@@ -767,8 +769,10 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) + } + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; ++ if (!priv) { ++ ret = -ENOMEM; ++ goto out; ++ } + + snd_soc_card_set_drvdata(card, priv); + +@@ -776,7 +780,8 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) + if (IS_ERR(priv->pinctrl)) { + dev_err(&pdev->dev, "%s devm_pinctrl_get failed\n", + __func__); +- return PTR_ERR(priv->pinctrl); ++ ret = PTR_ERR(priv->pinctrl); ++ goto out; + } + + for (i = 0; i < PIN_STATE_MAX; i++) { +@@ -809,6 +814,7 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) + + ret = devm_snd_soc_register_card(&pdev->dev, card); + ++out: + of_node_put(platform_node); + of_node_put(ec_codec); + of_node_put(hdmi_codec); +diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c +index cfca6bdee8345..90ec0d0a83927 100644 +--- a/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c ++++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c +@@ -192,7 +192,7 @@ static int mt8186_mt6366_da7219_max98357_hdmi_init(struct snd_soc_pcm_runtime *r + struct mt8186_mt6366_da7219_max98357_priv *priv = soc_card_data->mach_priv; + int ret; + +- ret = mt8186_dai_i2s_set_share(afe, "I2S3", "I2S2"); ++ ret = mt8186_dai_i2s_set_share(afe, "I2S2", "I2S3"); + if (ret) { + dev_err(rtd->dev, "Failed to set up shared clocks\n"); + return ret; +diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c +index 2414c5b77233c..60fa55d0c91f0 100644 +--- a/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c ++++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c +@@ -168,7 +168,7 @@ static int mt8186_mt6366_rt1019_rt5682s_hdmi_init(struct snd_soc_pcm_runtime *rt + struct mt8186_mt6366_rt1019_rt5682s_priv *priv = soc_card_data->mach_priv; + int ret; + +- ret = mt8186_dai_i2s_set_share(afe, "I2S3", "I2S2"); ++ ret = mt8186_dai_i2s_set_share(afe, "I2S2", "I2S3"); + if (ret) { + dev_err(rtd->dev, "Failed to set up shared clocks\n"); + return ret; +diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c +index 5d520e18e512f..99b245e3079a2 100644 +--- a/sound/soc/pxa/mmp-pcm.c ++++ b/sound/soc/pxa/mmp-pcm.c +@@ -98,7 +98,7 @@ static bool filter(struct dma_chan *chan, void *param) + + devname = kasprintf(GFP_KERNEL, "%s.%d", dma_data->dma_res->name, + dma_data->ssp_id); +- if ((strcmp(dev_name(chan->device->dev), devname) == 0) && ++ if (devname && (strcmp(dev_name(chan->device->dev), devname) == 0) && + (chan->chan_id == dma_data->dma_res->start)) { + found = true; + } +diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig +index 8c7398bc1ca89..96a6d4731e6fd 100644 +--- a/sound/soc/qcom/Kconfig ++++ b/sound/soc/qcom/Kconfig +@@ -2,6 +2,7 @@ + menuconfig SND_SOC_QCOM + tristate "ASoC support for QCOM platforms" + depends on ARCH_QCOM || COMPILE_TEST ++ imply SND_SOC_QCOM_COMMON + help + Say Y or M if you want to add support to use audio devices + in Qualcomm Technologies SOC-based platforms. +@@ -59,13 +60,14 @@ config SND_SOC_STORM + config SND_SOC_APQ8016_SBC + tristate "SoC Audio support for APQ8016 SBC platforms" + select SND_SOC_LPASS_APQ8016 +- select SND_SOC_QCOM_COMMON ++ depends on SND_SOC_QCOM_COMMON + help + Support for Qualcomm Technologies LPASS audio block in + APQ8016 SOC-based systems. + Say Y if you want to use audio devices on MI2S. + + config SND_SOC_QCOM_COMMON ++ depends on SOUNDWIRE + tristate + + config SND_SOC_QDSP6_COMMON +@@ -142,7 +144,7 @@ config SND_SOC_MSM8996 + depends on QCOM_APR + depends on COMMON_CLK + select SND_SOC_QDSP6 +- select SND_SOC_QCOM_COMMON ++ depends on SND_SOC_QCOM_COMMON + help + Support for Qualcomm Technologies LPASS audio block in + APQ8096 SoC-based systems. +@@ -153,7 +155,7 @@ config SND_SOC_SDM845 + depends on QCOM_APR && I2C && SOUNDWIRE + depends on COMMON_CLK + select SND_SOC_QDSP6 +- select SND_SOC_QCOM_COMMON ++ depends on SND_SOC_QCOM_COMMON + select SND_SOC_RT5663 + select SND_SOC_MAX98927 + imply SND_SOC_CROS_EC_CODEC +@@ -167,7 +169,7 @@ config SND_SOC_SM8250 + depends on QCOM_APR && SOUNDWIRE + depends on COMMON_CLK + select SND_SOC_QDSP6 +- select SND_SOC_QCOM_COMMON ++ depends on SND_SOC_QCOM_COMMON + help + To add support for audio on Qualcomm Technologies Inc. + SM8250 SoC-based systems. +@@ -178,7 +180,7 @@ config SND_SOC_SC8280XP + depends on QCOM_APR && SOUNDWIRE + depends on COMMON_CLK + select SND_SOC_QDSP6 +- select SND_SOC_QCOM_COMMON ++ depends on SND_SOC_QCOM_COMMON + help + To add support for audio on Qualcomm Technologies Inc. + SC8280XP SoC-based systems. +@@ -188,7 +190,7 @@ config SND_SOC_SC7180 + tristate "SoC Machine driver for SC7180 boards" + depends on I2C && GPIOLIB + depends on SOUNDWIRE || SOUNDWIRE=n +- select SND_SOC_QCOM_COMMON ++ depends on SND_SOC_QCOM_COMMON + select SND_SOC_LPASS_SC7180 + select SND_SOC_MAX98357A + select SND_SOC_RT5682_I2C +@@ -202,7 +204,7 @@ config SND_SOC_SC7180 + config SND_SOC_SC7280 + tristate "SoC Machine driver for SC7280 boards" + depends on I2C && SOUNDWIRE +- select SND_SOC_QCOM_COMMON ++ depends on SND_SOC_QCOM_COMMON + select SND_SOC_LPASS_SC7280 + select SND_SOC_MAX98357A + select SND_SOC_WCD938X_SDW +diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c +index 69dd3b504e209..49c74c1662a3f 100644 +--- a/sound/soc/qcom/common.c ++++ b/sound/soc/qcom/common.c +@@ -180,7 +180,6 @@ err_put_np: + } + EXPORT_SYMBOL_GPL(qcom_snd_parse_of); + +-#if IS_ENABLED(CONFIG_SOUNDWIRE) + int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, + struct sdw_stream_runtime *sruntime, + bool *stream_prepared) +@@ -294,7 +293,6 @@ int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream, + return 0; + } + EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_free); +-#endif + + int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_jack *jack, bool *jack_setup) +diff --git a/sound/soc/qcom/common.h b/sound/soc/qcom/common.h +index c5472a642de08..3ef5bb6d12df7 100644 +--- a/sound/soc/qcom/common.h ++++ b/sound/soc/qcom/common.h +@@ -11,7 +11,6 @@ int qcom_snd_parse_of(struct snd_soc_card *card); + int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_jack *jack, bool *jack_setup); + +-#if IS_ENABLED(CONFIG_SOUNDWIRE) + int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, + struct sdw_stream_runtime *runtime, + bool *stream_prepared); +@@ -21,26 +20,4 @@ int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream, + int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream, + struct sdw_stream_runtime *sruntime, + bool *stream_prepared); +-#else +-static inline int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, +- struct sdw_stream_runtime *runtime, +- bool *stream_prepared) +-{ +- return -ENOTSUPP; +-} +- +-static inline int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream, +- struct snd_pcm_hw_params *params, +- struct sdw_stream_runtime **psruntime) +-{ +- return -ENOTSUPP; +-} +- +-static inline int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream, +- struct sdw_stream_runtime *sruntime, +- bool *stream_prepared) +-{ +- return -ENOTSUPP; +-} +-#endif + #endif +diff --git a/sound/soc/qcom/lpass-sc7180.c b/sound/soc/qcom/lpass-sc7180.c +index 77a556b27cf09..24a1c121cb2e9 100644 +--- a/sound/soc/qcom/lpass-sc7180.c ++++ b/sound/soc/qcom/lpass-sc7180.c +@@ -131,6 +131,9 @@ static int sc7180_lpass_init(struct platform_device *pdev) + + drvdata->clks = devm_kcalloc(dev, variant->num_clks, + sizeof(*drvdata->clks), GFP_KERNEL); ++ if (!drvdata->clks) ++ return -ENOMEM; ++ + drvdata->num_clks = variant->num_clks; + + for (i = 0; i < drvdata->num_clks; i++) +diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c +index a7549f8272359..5b1e47bdc376b 100644 +--- a/sound/soc/rockchip/rockchip_pdm.c ++++ b/sound/soc/rockchip/rockchip_pdm.c +@@ -431,6 +431,7 @@ static int rockchip_pdm_runtime_resume(struct device *dev) + + ret = clk_prepare_enable(pdm->hclk); + if (ret) { ++ clk_disable_unprepare(pdm->clk); + dev_err(pdm->dev, "hclock enable failed %d\n", ret); + return ret; + } +diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c +index 8bef572d3cbc1..5b4f004575879 100644 +--- a/sound/soc/rockchip/rockchip_spdif.c ++++ b/sound/soc/rockchip/rockchip_spdif.c +@@ -88,6 +88,7 @@ static int __maybe_unused rk_spdif_runtime_resume(struct device *dev) + + ret = clk_prepare_enable(spdif->hclk); + if (ret) { ++ clk_disable_unprepare(spdif->mclk); + dev_err(spdif->dev, "hclk clock enable failed %d\n", ret); + return ret; + } +diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c +index 310cd6fb0038a..4aaf0784940b5 100644 +--- a/sound/usb/endpoint.c ++++ b/sound/usb/endpoint.c +@@ -1673,6 +1673,13 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, bool keep_pending) + stop_urbs(ep, false, keep_pending); + if (ep->clock_ref) + atomic_dec(&ep->clock_ref->locked); ++ ++ if (ep->chip->quirk_flags & QUIRK_FLAG_FORCE_IFACE_RESET && ++ usb_pipeout(ep->pipe)) { ++ ep->need_prepare = true; ++ if (ep->iface_ref) ++ ep->iface_ref->need_setup = true; ++ } + } + } + +diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c +index 59faa5a9a7141..b67617b68e509 100644 +--- a/sound/usb/line6/driver.c ++++ b/sound/usb/line6/driver.c +@@ -304,7 +304,8 @@ static void line6_data_received(struct urb *urb) + for (;;) { + done = + line6_midibuf_read(mb, line6->buffer_message, +- LINE6_MIDI_MESSAGE_MAXLEN); ++ LINE6_MIDI_MESSAGE_MAXLEN, ++ LINE6_MIDIBUF_READ_RX); + + if (done <= 0) + break; +diff --git a/sound/usb/line6/midi.c b/sound/usb/line6/midi.c +index ba0e2b7e8fe19..0838632c788e4 100644 +--- a/sound/usb/line6/midi.c ++++ b/sound/usb/line6/midi.c +@@ -44,7 +44,8 @@ static void line6_midi_transmit(struct snd_rawmidi_substream *substream) + int req, done; + + for (;;) { +- req = min(line6_midibuf_bytes_free(mb), line6->max_packet_size); ++ req = min3(line6_midibuf_bytes_free(mb), line6->max_packet_size, ++ LINE6_FALLBACK_MAXPACKETSIZE); + done = snd_rawmidi_transmit_peek(substream, chunk, req); + + if (done == 0) +@@ -56,7 +57,8 @@ static void line6_midi_transmit(struct snd_rawmidi_substream *substream) + + for (;;) { + done = line6_midibuf_read(mb, chunk, +- LINE6_FALLBACK_MAXPACKETSIZE); ++ LINE6_FALLBACK_MAXPACKETSIZE, ++ LINE6_MIDIBUF_READ_TX); + + if (done == 0) + break; +diff --git a/sound/usb/line6/midibuf.c b/sound/usb/line6/midibuf.c +index 6a70463f82c4e..e7f830f7526c9 100644 +--- a/sound/usb/line6/midibuf.c ++++ b/sound/usb/line6/midibuf.c +@@ -9,6 +9,7 @@ + + #include "midibuf.h" + ++ + static int midibuf_message_length(unsigned char code) + { + int message_length; +@@ -20,12 +21,7 @@ static int midibuf_message_length(unsigned char code) + + message_length = length[(code >> 4) - 8]; + } else { +- /* +- Note that according to the MIDI specification 0xf2 is +- the "Song Position Pointer", but this is used by Line 6 +- to send sysex messages to the host. +- */ +- static const int length[] = { -1, 2, -1, 2, -1, -1, 1, 1, 1, 1, ++ static const int length[] = { -1, 2, 2, 2, -1, -1, 1, 1, 1, -1, + 1, 1, 1, -1, 1, 1 + }; + message_length = length[code & 0x0f]; +@@ -125,7 +121,7 @@ int line6_midibuf_write(struct midi_buffer *this, unsigned char *data, + } + + int line6_midibuf_read(struct midi_buffer *this, unsigned char *data, +- int length) ++ int length, int read_type) + { + int bytes_used; + int length1, length2; +@@ -148,9 +144,22 @@ int line6_midibuf_read(struct midi_buffer *this, unsigned char *data, + + length1 = this->size - this->pos_read; + +- /* check MIDI command length */ + command = this->buf[this->pos_read]; ++ /* ++ PODxt always has status byte lower nibble set to 0010, ++ when it means to send 0000, so we correct if here so ++ that control/program changes come on channel 1 and ++ sysex message status byte is correct ++ */ ++ if (read_type == LINE6_MIDIBUF_READ_RX) { ++ if (command == 0xb2 || command == 0xc2 || command == 0xf2) { ++ unsigned char fixed = command & 0xf0; ++ this->buf[this->pos_read] = fixed; ++ command = fixed; ++ } ++ } + ++ /* check MIDI command length */ + if (command & 0x80) { + midi_length = midibuf_message_length(command); + this->command_prev = command; +diff --git a/sound/usb/line6/midibuf.h b/sound/usb/line6/midibuf.h +index 124a8f9f7e96c..542e8d836f87d 100644 +--- a/sound/usb/line6/midibuf.h ++++ b/sound/usb/line6/midibuf.h +@@ -8,6 +8,9 @@ + #ifndef MIDIBUF_H + #define MIDIBUF_H + ++#define LINE6_MIDIBUF_READ_TX 0 ++#define LINE6_MIDIBUF_READ_RX 1 ++ + struct midi_buffer { + unsigned char *buf; + int size; +@@ -23,7 +26,7 @@ extern void line6_midibuf_destroy(struct midi_buffer *mb); + extern int line6_midibuf_ignore(struct midi_buffer *mb, int length); + extern int line6_midibuf_init(struct midi_buffer *mb, int size, int split); + extern int line6_midibuf_read(struct midi_buffer *mb, unsigned char *data, +- int length); ++ int length, int read_type); + extern void line6_midibuf_reset(struct midi_buffer *mb); + extern int line6_midibuf_write(struct midi_buffer *mb, unsigned char *data, + int length); +diff --git a/sound/usb/line6/pod.c b/sound/usb/line6/pod.c +index cd41aa7f03851..d173971e5f029 100644 +--- a/sound/usb/line6/pod.c ++++ b/sound/usb/line6/pod.c +@@ -159,8 +159,9 @@ static struct line6_pcm_properties pod_pcm_properties = { + .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */ + }; + ++ + static const char pod_version_header[] = { +- 0xf2, 0x7e, 0x7f, 0x06, 0x02 ++ 0xf0, 0x7e, 0x7f, 0x06, 0x02 + }; + + static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code, +diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c +index 8ed165f036a01..9557bd4d1bbca 100644 +--- a/sound/usb/pcm.c ++++ b/sound/usb/pcm.c +@@ -604,6 +604,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_usb_substream *subs = runtime->private_data; + struct snd_usb_audio *chip = subs->stream->chip; ++ int retry = 0; + int ret; + + ret = snd_usb_lock_shutdown(chip); +@@ -614,6 +615,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) + goto unlock; + } + ++ again: + if (subs->sync_endpoint) { + ret = snd_usb_endpoint_prepare(chip, subs->sync_endpoint); + if (ret < 0) +@@ -638,9 +640,16 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) + + subs->lowlatency_playback = lowlatency_playback_available(runtime, subs); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && +- !subs->lowlatency_playback) ++ !subs->lowlatency_playback) { + ret = start_endpoints(subs); +- ++ /* if XRUN happens at starting streams (possibly with implicit ++ * fb case), restart again, but only try once. ++ */ ++ if (ret == -EPIPE && !retry++) { ++ sync_pending_stops(subs); ++ goto again; ++ } ++ } + unlock: + snd_usb_unlock_shutdown(chip); + return ret; +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index 874fcf245747f..271884e350035 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -76,6 +76,8 @@ + { USB_DEVICE_VENDOR_SPEC(0x041e, 0x3f0a) }, + /* E-Mu 0204 USB */ + { USB_DEVICE_VENDOR_SPEC(0x041e, 0x3f19) }, ++/* Ktmicro Usb_audio device */ ++{ USB_DEVICE_VENDOR_SPEC(0x31b2, 0x0011) }, + + /* + * Creative Technology, Ltd Live! Cam Sync HD [VF0770] +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 0f4dd3503a6a9..58b37bfc885cb 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -2044,6 +2044,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + DEVICE_FLG(0x0644, 0x804a, /* TEAC UD-301 */ + QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY | + QUIRK_FLAG_IFACE_DELAY), ++ DEVICE_FLG(0x0644, 0x805f, /* TEAC Model 12 */ ++ QUIRK_FLAG_FORCE_IFACE_RESET), + DEVICE_FLG(0x06f8, 0xb000, /* Hercules DJ Console (Windows Edition) */ + QUIRK_FLAG_IGNORE_CTL_ERROR), + DEVICE_FLG(0x06f8, 0xd002, /* Hercules DJ Console (Macintosh Edition) */ +diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h +index e97141ef730ad..2aba508a48312 100644 +--- a/sound/usb/usbaudio.h ++++ b/sound/usb/usbaudio.h +@@ -172,6 +172,9 @@ extern bool snd_usb_skip_validation; + * Don't apply implicit feedback sync mode + * QUIRK_FLAG_IFACE_SKIP_CLOSE + * Don't closed interface during setting sample rate ++ * QUIRK_FLAG_FORCE_IFACE_RESET ++ * Force an interface reset whenever stopping & restarting a stream ++ * (e.g. after xrun) + */ + + #define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) +@@ -194,5 +197,6 @@ extern bool snd_usb_skip_validation; + #define QUIRK_FLAG_GENERIC_IMPLICIT_FB (1U << 17) + #define QUIRK_FLAG_SKIP_IMPLICIT_FB (1U << 18) + #define QUIRK_FLAG_IFACE_SKIP_CLOSE (1U << 19) ++#define QUIRK_FLAG_FORCE_IFACE_RESET (1U << 20) + + #endif /* __USBAUDIO_H */ +diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c +index 0cdb4f7115101..e7a11cff7245a 100644 +--- a/tools/bpf/bpftool/common.c ++++ b/tools/bpf/bpftool/common.c +@@ -499,6 +499,7 @@ static int do_build_table_cb(const char *fpath, const struct stat *sb, + if (err) { + p_err("failed to append entry to hashmap for ID %u, path '%s': %s", + pinned_info.id, path, strerror(errno)); ++ free(path); + goto out_close; + } + +diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h +index 9c50beabdd145..fddc05c667b5d 100644 +--- a/tools/lib/bpf/bpf.h ++++ b/tools/lib/bpf/bpf.h +@@ -393,8 +393,15 @@ LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, + __u32 *buf_len, __u32 *prog_id, __u32 *fd_type, + __u64 *probe_offset, __u64 *probe_addr); + ++#ifdef __cplusplus ++/* forward-declaring enums in C++ isn't compatible with pure C enums, so ++ * instead define bpf_enable_stats() as accepting int as an input ++ */ ++LIBBPF_API int bpf_enable_stats(int type); ++#else + enum bpf_stats_type; /* defined in up-to-date linux/bpf.h */ + LIBBPF_API int bpf_enable_stats(enum bpf_stats_type type); ++#endif + + struct bpf_prog_bind_opts { + size_t sz; /* size of this struct for forward/backward compatibility */ +diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c +index d88647da2c7fc..675a0df5c840f 100644 +--- a/tools/lib/bpf/btf.c ++++ b/tools/lib/bpf/btf.c +@@ -3887,14 +3887,14 @@ static inline __u16 btf_fwd_kind(struct btf_type *t) + } + + /* Check if given two types are identical ARRAY definitions */ +-static int btf_dedup_identical_arrays(struct btf_dedup *d, __u32 id1, __u32 id2) ++static bool btf_dedup_identical_arrays(struct btf_dedup *d, __u32 id1, __u32 id2) + { + struct btf_type *t1, *t2; + + t1 = btf_type_by_id(d->btf, id1); + t2 = btf_type_by_id(d->btf, id2); + if (!btf_is_array(t1) || !btf_is_array(t2)) +- return 0; ++ return false; + + return btf_equal_array(t1, t2); + } +@@ -3918,7 +3918,9 @@ static bool btf_dedup_identical_structs(struct btf_dedup *d, __u32 id1, __u32 id + 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) ++ if (m1->type != m2->type && ++ !btf_dedup_identical_arrays(d, m1->type, m2->type) && ++ !btf_dedup_identical_structs(d, m1->type, m2->type)) + return false; + } + return true; +diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c +index 4221f73a74d01..0b470169729e6 100644 +--- a/tools/lib/bpf/btf_dump.c ++++ b/tools/lib/bpf/btf_dump.c +@@ -219,6 +219,17 @@ static int btf_dump_resize(struct btf_dump *d) + return 0; + } + ++static void btf_dump_free_names(struct hashmap *map) ++{ ++ size_t bkt; ++ struct hashmap_entry *cur; ++ ++ hashmap__for_each_entry(map, cur, bkt) ++ free((void *)cur->key); ++ ++ hashmap__free(map); ++} ++ + void btf_dump__free(struct btf_dump *d) + { + int i; +@@ -237,8 +248,8 @@ void btf_dump__free(struct btf_dump *d) + free(d->cached_names); + free(d->emit_queue); + free(d->decl_stack); +- hashmap__free(d->type_names); +- hashmap__free(d->ident_names); ++ btf_dump_free_names(d->type_names); ++ btf_dump_free_names(d->ident_names); + + free(d); + } +@@ -1520,11 +1531,23 @@ static void btf_dump_emit_type_cast(struct btf_dump *d, __u32 id, + static size_t btf_dump_name_dups(struct btf_dump *d, struct hashmap *name_map, + const char *orig_name) + { ++ char *old_name, *new_name; + size_t dup_cnt = 0; ++ int err; ++ ++ new_name = strdup(orig_name); ++ if (!new_name) ++ return 1; + + hashmap__find(name_map, orig_name, (void **)&dup_cnt); + dup_cnt++; +- hashmap__set(name_map, orig_name, (void *)dup_cnt, NULL, NULL); ++ ++ err = hashmap__set(name_map, new_name, (void *)dup_cnt, ++ (const void **)&old_name, NULL); ++ if (err) ++ free(new_name); ++ ++ free(old_name); + + return dup_cnt; + } +@@ -1963,7 +1986,7 @@ static int btf_dump_struct_data(struct btf_dump *d, + { + const struct btf_member *m = btf_members(t); + __u16 n = btf_vlen(t); +- int i, err; ++ int i, err = 0; + + /* note that we increment depth before calling btf_dump_print() below; + * this is intentional. btf_dump_data_newline() will not print a +diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c +index 91b7106a4a735..b9a29d1053765 100644 +--- a/tools/lib/bpf/libbpf.c ++++ b/tools/lib/bpf/libbpf.c +@@ -597,7 +597,7 @@ struct elf_state { + size_t shstrndx; /* section index for section name strings */ + size_t strtabidx; + struct elf_sec_desc *secs; +- int sec_cnt; ++ size_t sec_cnt; + int btf_maps_shndx; + __u32 btf_maps_sec_btf_id; + int text_shndx; +@@ -1408,6 +1408,10 @@ static int bpf_object__check_endianness(struct bpf_object *obj) + static int + bpf_object__init_license(struct bpf_object *obj, void *data, size_t size) + { ++ if (!data) { ++ pr_warn("invalid license section in %s\n", obj->path); ++ return -LIBBPF_ERRNO__FORMAT; ++ } + /* libbpf_strlcpy() only copies first N - 1 bytes, so size + 1 won't + * go over allowed ELF data section buffer + */ +@@ -1421,7 +1425,7 @@ bpf_object__init_kversion(struct bpf_object *obj, void *data, size_t size) + { + __u32 kver; + +- if (size != sizeof(kver)) { ++ if (!data || size != sizeof(kver)) { + pr_warn("invalid kver section in %s\n", obj->path); + return -LIBBPF_ERRNO__FORMAT; + } +@@ -3312,10 +3316,15 @@ static int bpf_object__elf_collect(struct bpf_object *obj) + Elf64_Shdr *sh; + + /* ELF section indices are 0-based, but sec #0 is special "invalid" +- * section. e_shnum does include sec #0, so e_shnum is the necessary +- * size of an array to keep all the sections. ++ * section. Since section count retrieved by elf_getshdrnum() does ++ * include sec #0, it is already the necessary size of an array to keep ++ * all the sections. + */ +- obj->efile.sec_cnt = obj->efile.ehdr->e_shnum; ++ if (elf_getshdrnum(obj->efile.elf, &obj->efile.sec_cnt)) { ++ pr_warn("elf: failed to get the number of sections for %s: %s\n", ++ obj->path, elf_errmsg(-1)); ++ return -LIBBPF_ERRNO__FORMAT; ++ } + obj->efile.secs = calloc(obj->efile.sec_cnt, sizeof(*obj->efile.secs)); + if (!obj->efile.secs) + return -ENOMEM; +@@ -4106,6 +4115,9 @@ static struct bpf_program *find_prog_by_sec_insn(const struct bpf_object *obj, + int l = 0, r = obj->nr_programs - 1, m; + struct bpf_program *prog; + ++ if (!obj->nr_programs) ++ return NULL; ++ + while (l < r) { + m = l + (r - l + 1) / 2; + prog = &obj->programs[m]; +diff --git a/tools/lib/bpf/usdt.c b/tools/lib/bpf/usdt.c +index e83b497c22454..49f3c3b7f6095 100644 +--- a/tools/lib/bpf/usdt.c ++++ b/tools/lib/bpf/usdt.c +@@ -1348,25 +1348,23 @@ static int calc_pt_regs_off(const char *reg_name) + + static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg) + { +- char *reg_name = NULL; ++ char reg_name[16]; + int arg_sz, len, reg_off; + long off; + +- if (sscanf(arg_str, " %d @ \[ %m[a-z0-9], %ld ] %n", &arg_sz, ®_name, &off, &len) == 3) { ++ if (sscanf(arg_str, " %d @ \[ %15[a-z0-9], %ld ] %n", &arg_sz, reg_name, &off, &len) == 3) { + /* Memory dereference case, e.g., -4@[sp, 96] */ + arg->arg_type = USDT_ARG_REG_DEREF; + arg->val_off = off; + reg_off = calc_pt_regs_off(reg_name); +- free(reg_name); + if (reg_off < 0) + return reg_off; + arg->reg_off = reg_off; +- } else if (sscanf(arg_str, " %d @ \[ %m[a-z0-9] ] %n", &arg_sz, ®_name, &len) == 2) { ++ } else if (sscanf(arg_str, " %d @ \[ %15[a-z0-9] ] %n", &arg_sz, reg_name, &len) == 2) { + /* Memory dereference case, e.g., -4@[sp] */ + arg->arg_type = USDT_ARG_REG_DEREF; + arg->val_off = 0; + reg_off = calc_pt_regs_off(reg_name); +- free(reg_name); + if (reg_off < 0) + return reg_off; + arg->reg_off = reg_off; +@@ -1375,12 +1373,11 @@ static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec + arg->arg_type = USDT_ARG_CONST; + arg->val_off = off; + arg->reg_off = 0; +- } else if (sscanf(arg_str, " %d @ %m[a-z0-9] %n", &arg_sz, ®_name, &len) == 2) { ++ } else if (sscanf(arg_str, " %d @ %15[a-z0-9] %n", &arg_sz, reg_name, &len) == 2) { + /* Register read case, e.g., -8@x4 */ + arg->arg_type = USDT_ARG_REG; + arg->val_off = 0; + reg_off = calc_pt_regs_off(reg_name); +- free(reg_name); + if (reg_off < 0) + return reg_off; + arg->reg_off = reg_off; +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index 43ec14c29a60c..51494c3002d91 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -207,7 +207,7 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func, + return false; + + insn = find_insn(file, func->sec, func->offset); +- if (!insn->func) ++ if (!insn || !insn->func) + return false; + + func_for_each_insn(file, func, insn) { +@@ -999,6 +999,16 @@ static const char *uaccess_safe_builtin[] = { + "__tsan_read_write4", + "__tsan_read_write8", + "__tsan_read_write16", ++ "__tsan_volatile_read1", ++ "__tsan_volatile_read2", ++ "__tsan_volatile_read4", ++ "__tsan_volatile_read8", ++ "__tsan_volatile_read16", ++ "__tsan_volatile_write1", ++ "__tsan_volatile_write2", ++ "__tsan_volatile_write4", ++ "__tsan_volatile_write8", ++ "__tsan_volatile_write16", + "__tsan_atomic8_load", + "__tsan_atomic16_load", + "__tsan_atomic32_load", +diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt +index 18fcc52809fbf..980fe2c292752 100644 +--- a/tools/perf/Documentation/perf-annotate.txt ++++ b/tools/perf/Documentation/perf-annotate.txt +@@ -41,7 +41,7 @@ OPTIONS + + -q:: + --quiet:: +- Do not show any message. (Suppress -v) ++ Do not show any warnings or messages. (Suppress -v) + + -n:: + --show-nr-samples:: +diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt +index be65bd55ab2aa..f3067a4af2940 100644 +--- a/tools/perf/Documentation/perf-diff.txt ++++ b/tools/perf/Documentation/perf-diff.txt +@@ -75,7 +75,7 @@ OPTIONS + + -q:: + --quiet:: +- Do not show any message. (Suppress -v) ++ Do not show any warnings or messages. (Suppress -v) + + -f:: + --force:: +diff --git a/tools/perf/Documentation/perf-lock.txt b/tools/perf/Documentation/perf-lock.txt +index 3b1e16563b795..4958a1ffa1cca 100644 +--- a/tools/perf/Documentation/perf-lock.txt ++++ b/tools/perf/Documentation/perf-lock.txt +@@ -42,7 +42,7 @@ COMMON OPTIONS + + -q:: + --quiet:: +- Do not show any message. (Suppress -v) ++ Do not show any warnings or messages. (Suppress -v) + + -D:: + --dump-raw-trace:: +diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt +index 080981d38d7ba..7f8e8ba3a7872 100644 +--- a/tools/perf/Documentation/perf-probe.txt ++++ b/tools/perf/Documentation/perf-probe.txt +@@ -57,7 +57,7 @@ OPTIONS + + -q:: + --quiet:: +- Be quiet (do not show any messages including errors). ++ Do not show any warnings or messages. + Can not use with -v. + + -a:: +diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt +index e41ae950fdc3b..9ea6d44aca58c 100644 +--- a/tools/perf/Documentation/perf-record.txt ++++ b/tools/perf/Documentation/perf-record.txt +@@ -282,7 +282,7 @@ OPTIONS + + -q:: + --quiet:: +- Don't print any message, useful for scripting. ++ Don't print any warnings or messages, useful for scripting. + + -v:: + --verbose:: +diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt +index 4533db2ee56bb..4fa509b159489 100644 +--- a/tools/perf/Documentation/perf-report.txt ++++ b/tools/perf/Documentation/perf-report.txt +@@ -27,7 +27,7 @@ OPTIONS + + -q:: + --quiet:: +- Do not show any message. (Suppress -v) ++ Do not show any warnings or messages. (Suppress -v) + + -n:: + --show-nr-samples:: +diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt +index d7ff1867feda6..18abdc1dce055 100644 +--- a/tools/perf/Documentation/perf-stat.txt ++++ b/tools/perf/Documentation/perf-stat.txt +@@ -354,8 +354,8 @@ forbids the event merging logic from sharing events between groups and + may be used to increase accuracy in this case. + + --quiet:: +-Don't print output. This is useful with perf stat record below to only +-write data to the perf.data file. ++Don't print output, warnings or messages. This is useful with perf stat ++record below to only write data to the perf.data file. + + STAT RECORD + ----------- +diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c +index e78dedf9e682c..9717c6c17433c 100644 +--- a/tools/perf/bench/numa.c ++++ b/tools/perf/bench/numa.c +@@ -16,6 +16,7 @@ + #include <sched.h> + #include <stdio.h> + #include <assert.h> ++#include <debug.h> + #include <malloc.h> + #include <signal.h> + #include <stdlib.h> +@@ -116,7 +117,6 @@ struct params { + long bytes_thread; + + int nr_tasks; +- bool show_quiet; + + bool show_convergence; + bool measure_convergence; +@@ -197,7 +197,8 @@ static const struct option options[] = { + OPT_BOOLEAN('c', "show_convergence", &p0.show_convergence, "show convergence details, " + "convergence is reached when each process (all its threads) is running on a single NUMA node."), + OPT_BOOLEAN('m', "measure_convergence", &p0.measure_convergence, "measure convergence latency"), +- OPT_BOOLEAN('q', "quiet" , &p0.show_quiet, "quiet mode"), ++ OPT_BOOLEAN('q', "quiet" , &quiet, ++ "quiet mode (do not show any warnings or messages)"), + OPT_BOOLEAN('S', "serialize-startup", &p0.serialize_startup,"serialize thread startup"), + + /* Special option string parsing callbacks: */ +@@ -1474,7 +1475,7 @@ static int init(void) + /* char array in count_process_nodes(): */ + BUG_ON(g->p.nr_nodes < 0); + +- if (g->p.show_quiet && !g->p.show_details) ++ if (quiet && !g->p.show_details) + g->p.show_details = -1; + + /* Some memory should be specified: */ +@@ -1553,7 +1554,7 @@ static void print_res(const char *name, double val, + if (!name) + name = "main,"; + +- if (!g->p.show_quiet) ++ if (!quiet) + printf(" %-30s %15.3f, %-15s %s\n", name, val, txt_unit, txt_short); + else + printf(" %14.3f %s\n", val, txt_long); +diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c +index f839e69492e80..517d928c00e3f 100644 +--- a/tools/perf/builtin-annotate.c ++++ b/tools/perf/builtin-annotate.c +@@ -525,7 +525,7 @@ int cmd_annotate(int argc, const char **argv) + OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"), + OPT_INCR('v', "verbose", &verbose, + "be more verbose (show symbol address, etc)"), +- OPT_BOOLEAN('q', "quiet", &quiet, "do now show any message"), ++ OPT_BOOLEAN('q', "quiet", &quiet, "do now show any warnings or messages"), + OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, + "dump raw trace in ASCII"), + #ifdef HAVE_GTK2_SUPPORT +diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c +index d925096dd7f02..ed07cc6cca56c 100644 +--- a/tools/perf/builtin-diff.c ++++ b/tools/perf/builtin-diff.c +@@ -1260,7 +1260,7 @@ static const char * const diff_usage[] = { + static const struct option options[] = { + OPT_INCR('v', "verbose", &verbose, + "be more verbose (show symbol address, etc)"), +- OPT_BOOLEAN('q', "quiet", &quiet, "Do not show any message"), ++ OPT_BOOLEAN('q', "quiet", &quiet, "Do not show any warnings or messages"), + OPT_BOOLEAN('b', "baseline-only", &show_baseline_only, + "Show only items with match in baseline"), + OPT_CALLBACK('c', "compute", &compute, +diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c +index 9722d4ab2e557..66520712a1675 100644 +--- a/tools/perf/builtin-lock.c ++++ b/tools/perf/builtin-lock.c +@@ -1869,7 +1869,7 @@ int cmd_lock(int argc, const char **argv) + "file", "vmlinux pathname"), + OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, + "file", "kallsyms pathname"), +- OPT_BOOLEAN('q', "quiet", &quiet, "Do not show any message"), ++ OPT_BOOLEAN('q', "quiet", &quiet, "Do not show any warnings or messages"), + OPT_END() + }; + +diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c +index f62298f5db3b4..ed73d0b89ca2d 100644 +--- a/tools/perf/builtin-probe.c ++++ b/tools/perf/builtin-probe.c +@@ -40,7 +40,6 @@ static struct { + int command; /* Command short_name */ + bool list_events; + bool uprobes; +- bool quiet; + bool target_used; + int nevents; + struct perf_probe_event events[MAX_PROBES]; +@@ -514,8 +513,8 @@ __cmd_probe(int argc, const char **argv) + struct option options[] = { + OPT_INCR('v', "verbose", &verbose, + "be more verbose (show parsed arguments, etc)"), +- OPT_BOOLEAN('q', "quiet", ¶ms.quiet, +- "be quiet (do not show any messages)"), ++ OPT_BOOLEAN('q', "quiet", &quiet, ++ "be quiet (do not show any warnings or messages)"), + OPT_CALLBACK_DEFAULT('l', "list", NULL, "[GROUP:]EVENT", + "list up probe events", + opt_set_filter_with_command, DEFAULT_LIST_FILTER), +@@ -613,6 +612,15 @@ __cmd_probe(int argc, const char **argv) + + argc = parse_options(argc, argv, options, probe_usage, + PARSE_OPT_STOP_AT_NON_OPTION); ++ ++ if (quiet) { ++ if (verbose != 0) { ++ pr_err(" Error: -v and -q are exclusive.\n"); ++ return -EINVAL; ++ } ++ verbose = -1; ++ } ++ + if (argc > 0) { + if (strcmp(argv[0], "-") == 0) { + usage_with_options_msg(probe_usage, options, +@@ -634,14 +642,6 @@ __cmd_probe(int argc, const char **argv) + if (ret) + return ret; + +- if (params.quiet) { +- if (verbose != 0) { +- pr_err(" Error: -v and -q are exclusive.\n"); +- return -EINVAL; +- } +- verbose = -1; +- } +- + if (probe_conf.max_probes == 0) + probe_conf.max_probes = MAX_PROBES; + +diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c +index e128b855dddec..59f3d98a0196d 100644 +--- a/tools/perf/builtin-record.c ++++ b/tools/perf/builtin-record.c +@@ -3388,7 +3388,7 @@ static struct option __record_options[] = { + &record_parse_callchain_opt), + OPT_INCR('v', "verbose", &verbose, + "be more verbose (show counter open errors, etc)"), +- OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), ++ OPT_BOOLEAN('q', "quiet", &quiet, "don't print any warnings or messages"), + OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, + "per thread counts"), + OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), +diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c +index 8361890176c23..b6d77d3da64f6 100644 +--- a/tools/perf/builtin-report.c ++++ b/tools/perf/builtin-report.c +@@ -1222,7 +1222,7 @@ int cmd_report(int argc, const char **argv) + "input file name"), + OPT_INCR('v', "verbose", &verbose, + "be more verbose (show symbol address, etc)"), +- OPT_BOOLEAN('q', "quiet", &quiet, "Do not show any message"), ++ OPT_BOOLEAN('q', "quiet", &quiet, "Do not show any warnings or messages"), + OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, + "dump raw trace in ASCII"), + OPT_BOOLEAN(0, "stats", &report.stats_mode, "Display event stats"), +diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c +index 265b051579726..978fdc60b4e84 100644 +--- a/tools/perf/builtin-stat.c ++++ b/tools/perf/builtin-stat.c +@@ -528,26 +528,14 @@ static int enable_counters(void) + return err; + } + +- if (stat_config.initial_delay < 0) { +- pr_info(EVLIST_DISABLED_MSG); +- return 0; +- } +- +- if (stat_config.initial_delay > 0) { +- pr_info(EVLIST_DISABLED_MSG); +- usleep(stat_config.initial_delay * USEC_PER_MSEC); +- } +- + /* + * We need to enable counters only if: + * - we don't have tracee (attaching to task or cpu) + * - we have initial delay configured + */ +- if (!target__none(&target) || stat_config.initial_delay) { ++ if (!target__none(&target)) { + if (!all_counters_use_bpf) + evlist__enable(evsel_list); +- if (stat_config.initial_delay > 0) +- pr_info(EVLIST_ENABLED_MSG); + } + return 0; + } +@@ -918,14 +906,27 @@ try_again_reset: + return err; + } + +- err = enable_counters(); +- if (err) +- return -1; ++ if (stat_config.initial_delay) { ++ pr_info(EVLIST_DISABLED_MSG); ++ } else { ++ err = enable_counters(); ++ if (err) ++ return -1; ++ } + + /* Exec the command, if any */ + if (forks) + evlist__start_workload(evsel_list); + ++ if (stat_config.initial_delay > 0) { ++ usleep(stat_config.initial_delay * USEC_PER_MSEC); ++ err = enable_counters(); ++ if (err) ++ return -1; ++ ++ pr_info(EVLIST_ENABLED_MSG); ++ } ++ + t0 = rdclock(); + clock_gettime(CLOCK_MONOTONIC, &ref_time); + +@@ -1023,7 +1024,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv) + /* Do not print anything if we record to the pipe. */ + if (STAT_RECORD && perf_stat.data.is_pipe) + return; +- if (stat_config.quiet) ++ if (quiet) + return; + + evlist__print_counters(evsel_list, &stat_config, &target, ts, argc, argv); +@@ -1273,8 +1274,8 @@ static struct option stat_options[] = { + "print summary for interval mode"), + OPT_BOOLEAN(0, "no-csv-summary", &stat_config.no_csv_summary, + "don't print 'summary' for CSV summary output"), +- OPT_BOOLEAN(0, "quiet", &stat_config.quiet, +- "don't print output (useful with record)"), ++ OPT_BOOLEAN(0, "quiet", &quiet, ++ "don't print any output, messages or warnings (useful with record)"), + OPT_CALLBACK(0, "cputype", &evsel_list, "hybrid cpu type", + "Only enable events on applying cpu with this type " + "for hybrid platform (e.g. core or atom)", +@@ -2277,7 +2278,7 @@ int cmd_stat(int argc, const char **argv) + goto out; + } + +- if (!output && !stat_config.quiet) { ++ if (!output && !quiet) { + struct timespec tm; + mode = append_file ? "a" : "w"; + +diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c +index d3c757769b965..3dcf6aed1ef71 100644 +--- a/tools/perf/builtin-trace.c ++++ b/tools/perf/builtin-trace.c +@@ -88,6 +88,8 @@ + # define F_LINUX_SPECIFIC_BASE 1024 + #endif + ++#define RAW_SYSCALL_ARGS_NUM 6 ++ + /* + * strtoul: Go from a string to a value, i.e. for msr: MSR_FS_BASE to 0xc0000100 + */ +@@ -108,7 +110,7 @@ struct syscall_fmt { + const char *sys_enter, + *sys_exit; + } bpf_prog_name; +- struct syscall_arg_fmt arg[6]; ++ struct syscall_arg_fmt arg[RAW_SYSCALL_ARGS_NUM]; + u8 nr_args; + bool errpid; + bool timeout; +@@ -1226,7 +1228,7 @@ struct syscall { + */ + struct bpf_map_syscall_entry { + bool enabled; +- u16 string_args_len[6]; ++ u16 string_args_len[RAW_SYSCALL_ARGS_NUM]; + }; + + /* +@@ -1658,7 +1660,7 @@ static int syscall__alloc_arg_fmts(struct syscall *sc, int nr_args) + { + int idx; + +- if (nr_args == 6 && sc->fmt && sc->fmt->nr_args != 0) ++ if (nr_args == RAW_SYSCALL_ARGS_NUM && sc->fmt && sc->fmt->nr_args != 0) + nr_args = sc->fmt->nr_args; + + sc->arg_fmt = calloc(nr_args, sizeof(*sc->arg_fmt)); +@@ -1791,11 +1793,11 @@ static int trace__read_syscall_info(struct trace *trace, int id) + #endif + sc = trace->syscalls.table + id; + if (sc->nonexistent) +- return 0; ++ return -EEXIST; + + if (name == NULL) { + sc->nonexistent = true; +- return 0; ++ return -EEXIST; + } + + sc->name = name; +@@ -1809,11 +1811,18 @@ static int trace__read_syscall_info(struct trace *trace, int id) + sc->tp_format = trace_event__tp_format("syscalls", tp_name); + } + +- if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ? 6 : sc->tp_format->format.nr_fields)) +- return -ENOMEM; +- +- if (IS_ERR(sc->tp_format)) ++ /* ++ * Fails to read trace point format via sysfs node, so the trace point ++ * doesn't exist. Set the 'nonexistent' flag as true. ++ */ ++ if (IS_ERR(sc->tp_format)) { ++ sc->nonexistent = true; + return PTR_ERR(sc->tp_format); ++ } ++ ++ if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ? ++ RAW_SYSCALL_ARGS_NUM : sc->tp_format->format.nr_fields)) ++ return -ENOMEM; + + sc->args = sc->tp_format->format.fields; + /* +@@ -2131,11 +2140,8 @@ static struct syscall *trace__syscall_info(struct trace *trace, + (err = trace__read_syscall_info(trace, id)) != 0) + goto out_cant_read; + +- if (trace->syscalls.table[id].name == NULL) { +- if (trace->syscalls.table[id].nonexistent) +- return NULL; ++ if (trace->syscalls.table && trace->syscalls.table[id].nonexistent) + goto out_cant_read; +- } + + return &trace->syscalls.table[id]; + +diff --git a/tools/perf/tests/shell/stat_all_pmu.sh b/tools/perf/tests/shell/stat_all_pmu.sh +index 9c9ef33e0b3c6..c779554191731 100755 +--- a/tools/perf/tests/shell/stat_all_pmu.sh ++++ b/tools/perf/tests/shell/stat_all_pmu.sh +@@ -4,17 +4,8 @@ + + set -e + +-for p in $(perf list --raw-dump pmu); do +- # In powerpc, skip the events for hv_24x7 and hv_gpci. +- # These events needs input values to be filled in for +- # core, chip, partition id based on system. +- # Example: hv_24x7/CPM_ADJUNCT_INST,domain=?,core=?/ +- # hv_gpci/event,partition_id=?/ +- # Hence skip these events for ppc. +- if echo "$p" |grep -Eq 'hv_24x7|hv_gpci' ; then +- echo "Skipping: Event '$p' in powerpc" +- continue +- fi ++# Test all PMU events; however exclude parametrized ones (name contains '?') ++for p in $(perf list --raw-dump pmu | sed 's/[[:graph:]]\+?[[:graph:]]\+[[:space:]]//g'); do + echo "Testing $p" + result=$(perf stat -e "$p" true 2>&1) + if ! echo "$result" | grep -q "$p" && ! echo "$result" | grep -q "<not supported>" ; then +diff --git a/tools/perf/ui/util.c b/tools/perf/ui/util.c +index 689b27c34246c..1d38ddf01b604 100644 +--- a/tools/perf/ui/util.c ++++ b/tools/perf/ui/util.c +@@ -15,6 +15,9 @@ static int perf_stdio__error(const char *format, va_list args) + + static int perf_stdio__warning(const char *format, va_list args) + { ++ if (quiet) ++ return 0; ++ + fprintf(stderr, "Warning:\n"); + vfprintf(stderr, format, args); + return 0; +@@ -45,6 +48,8 @@ int ui__warning(const char *format, ...) + { + int ret; + va_list args; ++ if (quiet) ++ return 0; + + va_start(args, format); + ret = perf_eops->warning(format, args); +diff --git a/tools/perf/util/bpf_off_cpu.c b/tools/perf/util/bpf_off_cpu.c +index c257813e674ef..01f70b8e705a8 100644 +--- a/tools/perf/util/bpf_off_cpu.c ++++ b/tools/perf/util/bpf_off_cpu.c +@@ -102,7 +102,7 @@ static void check_sched_switch_args(void) + const struct btf_type *t1, *t2, *t3; + u32 type_id; + +- type_id = btf__find_by_name_kind(btf, "bpf_trace_sched_switch", ++ type_id = btf__find_by_name_kind(btf, "btf_trace_sched_switch", + BTF_KIND_TYPEDEF); + if ((s32)type_id < 0) + return; +diff --git a/tools/perf/util/branch.h b/tools/perf/util/branch.h +index f838b23db1804..dca75cad96f68 100644 +--- a/tools/perf/util/branch.h ++++ b/tools/perf/util/branch.h +@@ -24,9 +24,10 @@ struct branch_flags { + u64 abort:1; + u64 cycles:16; + u64 type:4; ++ u64 spec:2; + u64 new_type:4; + u64 priv:3; +- u64 reserved:33; ++ u64 reserved:31; + }; + }; + }; +diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c +index 65e6c22f38e4f..190e818a07176 100644 +--- a/tools/perf/util/debug.c ++++ b/tools/perf/util/debug.c +@@ -241,6 +241,10 @@ int perf_quiet_option(void) + opt++; + } + ++ /* For debug variables that are used as bool types, set to 0. */ ++ redirect_to_stderr = 0; ++ debug_peo_args = 0; ++ + return 0; + } + +diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c +index ba66bb7fc1ca7..bc866d18973e4 100644 +--- a/tools/perf/util/stat-display.c ++++ b/tools/perf/util/stat-display.c +@@ -704,7 +704,7 @@ static void uniquify_event_name(struct evsel *counter) + counter->name = new_name; + } + } else { +- if (perf_pmu__has_hybrid()) { ++ if (evsel__is_hybrid(counter)) { + ret = asprintf(&new_name, "%s/%s/", + counter->pmu_name, counter->name); + } else { +@@ -744,26 +744,14 @@ static void collect_all_aliases(struct perf_stat_config *config, struct evsel *c + } + } + +-static bool is_uncore(struct evsel *evsel) +-{ +- struct perf_pmu *pmu = evsel__find_pmu(evsel); +- +- return pmu && pmu->is_uncore; +-} +- +-static bool hybrid_uniquify(struct evsel *evsel) +-{ +- return perf_pmu__has_hybrid() && !is_uncore(evsel); +-} +- + static bool hybrid_merge(struct evsel *counter, struct perf_stat_config *config, + bool check) + { +- if (hybrid_uniquify(counter)) { ++ if (evsel__is_hybrid(counter)) { + if (check) +- return config && config->hybrid_merge; ++ return config->hybrid_merge; + else +- return config && !config->hybrid_merge; ++ return !config->hybrid_merge; + } + + return false; +@@ -1142,11 +1130,16 @@ static void print_metric_headers(struct perf_stat_config *config, + struct evlist *evlist, + const char *prefix, bool no_indent) + { +- struct perf_stat_output_ctx out; + struct evsel *counter; + struct outstate os = { + .fh = config->output + }; ++ struct perf_stat_output_ctx out = { ++ .ctx = &os, ++ .print_metric = print_metric_header, ++ .new_line = new_line_metric, ++ .force_header = true, ++ }; + bool first = true; + + if (config->json_output && !config->interval) +@@ -1170,13 +1163,11 @@ static void print_metric_headers(struct perf_stat_config *config, + /* Print metrics headers only */ + evlist__for_each_entry(evlist, counter) { + os.evsel = counter; +- out.ctx = &os; +- out.print_metric = print_metric_header; ++ + if (!first && config->json_output) + fprintf(config->output, ", "); + first = false; +- out.new_line = new_line_metric; +- out.force_header = true; ++ + perf_stat__print_shadow_stats(config, counter, 0, + 0, + &out, +diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h +index b0899c6e002f5..35c940d7f29cd 100644 +--- a/tools/perf/util/stat.h ++++ b/tools/perf/util/stat.h +@@ -139,7 +139,6 @@ struct perf_stat_config { + bool metric_no_group; + bool metric_no_merge; + bool stop_read_counter; +- bool quiet; + bool iostat_run; + char *user_requested_cpu_list; + bool system_wide; +diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c +index 647b7dff8ef36..80345695b1360 100644 +--- a/tools/perf/util/symbol-elf.c ++++ b/tools/perf/util/symbol-elf.c +@@ -1303,7 +1303,7 @@ dso__load_sym_internal(struct dso *dso, struct map *map, struct symsrc *syms_ss, + (!used_opd && syms_ss->adjust_symbols)) { + GElf_Phdr phdr; + +- if (elf_read_program_header(syms_ss->elf, ++ if (elf_read_program_header(runtime_ss->elf, + (u64)sym.st_value, &phdr)) { + pr_debug4("%s: failed to find program header for " + "symbol: %s st_value: %#" PRIx64 "\n", +diff --git a/tools/testing/selftests/bpf/config b/tools/testing/selftests/bpf/config +index 9213565c03117..59cec4244b3a7 100644 +--- a/tools/testing/selftests/bpf/config ++++ b/tools/testing/selftests/bpf/config +@@ -13,6 +13,7 @@ CONFIG_CRYPTO_USER_API_HASH=y + CONFIG_DYNAMIC_FTRACE=y + CONFIG_FPROBE=y + CONFIG_FTRACE_SYSCALLS=y ++CONFIG_FUNCTION_ERROR_INJECTION=y + CONFIG_FUNCTION_TRACER=y + CONFIG_GENEVE=y + CONFIG_IKCONFIG=y +diff --git a/tools/testing/selftests/bpf/network_helpers.c b/tools/testing/selftests/bpf/network_helpers.c +index bec15558fd938..1f37adff7632c 100644 +--- a/tools/testing/selftests/bpf/network_helpers.c ++++ b/tools/testing/selftests/bpf/network_helpers.c +@@ -426,6 +426,10 @@ static int setns_by_fd(int nsfd) + if (!ASSERT_OK(err, "mount /sys/fs/bpf")) + return err; + ++ err = mount("debugfs", "/sys/kernel/debug", "debugfs", 0, NULL); ++ if (!ASSERT_OK(err, "mount /sys/kernel/debug")) ++ return err; ++ + return 0; + } + +diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c +index 3369c5ec3a17c..ecde236047fe1 100644 +--- a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c ++++ b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c +@@ -1498,7 +1498,6 @@ static noinline int trigger_func(int arg) + static void test_task_vma_offset_common(struct bpf_iter_attach_opts *opts, bool one_proc) + { + struct bpf_iter_vma_offset *skel; +- struct bpf_link *link; + char buf[16] = {}; + int iter_fd, len; + int pgsz, shift; +@@ -1513,11 +1512,11 @@ static void test_task_vma_offset_common(struct bpf_iter_attach_opts *opts, bool + ; + skel->bss->page_shift = shift; + +- link = bpf_program__attach_iter(skel->progs.get_vma_offset, opts); +- if (!ASSERT_OK_PTR(link, "attach_iter")) +- return; ++ skel->links.get_vma_offset = bpf_program__attach_iter(skel->progs.get_vma_offset, opts); ++ if (!ASSERT_OK_PTR(skel->links.get_vma_offset, "attach_iter")) ++ goto exit; + +- iter_fd = bpf_iter_create(bpf_link__fd(link)); ++ iter_fd = bpf_iter_create(bpf_link__fd(skel->links.get_vma_offset)); + if (!ASSERT_GT(iter_fd, 0, "create_iter")) + goto exit; + +@@ -1535,7 +1534,7 @@ static void test_task_vma_offset_common(struct bpf_iter_attach_opts *opts, bool + close(iter_fd); + + exit: +- bpf_link__destroy(link); ++ bpf_iter_vma_offset__destroy(skel); + } + + static void test_task_vma_offset(void) +diff --git a/tools/testing/selftests/bpf/prog_tests/empty_skb.c b/tools/testing/selftests/bpf/prog_tests/empty_skb.c +new file mode 100644 +index 0000000000000..0613f3bb8b5e4 +--- /dev/null ++++ b/tools/testing/selftests/bpf/prog_tests/empty_skb.c +@@ -0,0 +1,146 @@ ++// SPDX-License-Identifier: GPL-2.0 ++#include <test_progs.h> ++#include <network_helpers.h> ++#include <net/if.h> ++#include "empty_skb.skel.h" ++ ++#define SYS(cmd) ({ \ ++ if (!ASSERT_OK(system(cmd), (cmd))) \ ++ goto out; \ ++}) ++ ++void serial_test_empty_skb(void) ++{ ++ LIBBPF_OPTS(bpf_test_run_opts, tattr); ++ struct empty_skb *bpf_obj = NULL; ++ struct nstoken *tok = NULL; ++ struct bpf_program *prog; ++ char eth_hlen_pp[15]; ++ char eth_hlen[14]; ++ int veth_ifindex; ++ int ipip_ifindex; ++ int err; ++ int i; ++ ++ struct { ++ const char *msg; ++ const void *data_in; ++ __u32 data_size_in; ++ int *ifindex; ++ int err; ++ int ret; ++ bool success_on_tc; ++ } tests[] = { ++ /* Empty packets are always rejected. */ ++ ++ { ++ /* BPF_PROG_RUN ETH_HLEN size check */ ++ .msg = "veth empty ingress packet", ++ .data_in = NULL, ++ .data_size_in = 0, ++ .ifindex = &veth_ifindex, ++ .err = -EINVAL, ++ }, ++ { ++ /* BPF_PROG_RUN ETH_HLEN size check */ ++ .msg = "ipip empty ingress packet", ++ .data_in = NULL, ++ .data_size_in = 0, ++ .ifindex = &ipip_ifindex, ++ .err = -EINVAL, ++ }, ++ ++ /* ETH_HLEN-sized packets: ++ * - can not be redirected at LWT_XMIT ++ * - can be redirected at TC to non-tunneling dest ++ */ ++ ++ { ++ /* __bpf_redirect_common */ ++ .msg = "veth ETH_HLEN packet ingress", ++ .data_in = eth_hlen, ++ .data_size_in = sizeof(eth_hlen), ++ .ifindex = &veth_ifindex, ++ .ret = -ERANGE, ++ .success_on_tc = true, ++ }, ++ { ++ /* __bpf_redirect_no_mac ++ * ++ * lwt: skb->len=0 <= skb_network_offset=0 ++ * tc: skb->len=14 <= skb_network_offset=14 ++ */ ++ .msg = "ipip ETH_HLEN packet ingress", ++ .data_in = eth_hlen, ++ .data_size_in = sizeof(eth_hlen), ++ .ifindex = &ipip_ifindex, ++ .ret = -ERANGE, ++ }, ++ ++ /* ETH_HLEN+1-sized packet should be redirected. */ ++ ++ { ++ .msg = "veth ETH_HLEN+1 packet ingress", ++ .data_in = eth_hlen_pp, ++ .data_size_in = sizeof(eth_hlen_pp), ++ .ifindex = &veth_ifindex, ++ }, ++ { ++ .msg = "ipip ETH_HLEN+1 packet ingress", ++ .data_in = eth_hlen_pp, ++ .data_size_in = sizeof(eth_hlen_pp), ++ .ifindex = &ipip_ifindex, ++ }, ++ }; ++ ++ SYS("ip netns add empty_skb"); ++ tok = open_netns("empty_skb"); ++ SYS("ip link add veth0 type veth peer veth1"); ++ SYS("ip link set dev veth0 up"); ++ SYS("ip link set dev veth1 up"); ++ SYS("ip addr add 10.0.0.1/8 dev veth0"); ++ SYS("ip addr add 10.0.0.2/8 dev veth1"); ++ veth_ifindex = if_nametoindex("veth0"); ++ ++ SYS("ip link add ipip0 type ipip local 10.0.0.1 remote 10.0.0.2"); ++ SYS("ip link set ipip0 up"); ++ SYS("ip addr add 192.168.1.1/16 dev ipip0"); ++ ipip_ifindex = if_nametoindex("ipip0"); ++ ++ bpf_obj = empty_skb__open_and_load(); ++ if (!ASSERT_OK_PTR(bpf_obj, "open skeleton")) ++ goto out; ++ ++ for (i = 0; i < ARRAY_SIZE(tests); i++) { ++ bpf_object__for_each_program(prog, bpf_obj->obj) { ++ char buf[128]; ++ bool at_tc = !strncmp(bpf_program__section_name(prog), "tc", 2); ++ ++ tattr.data_in = tests[i].data_in; ++ tattr.data_size_in = tests[i].data_size_in; ++ ++ tattr.data_size_out = 0; ++ bpf_obj->bss->ifindex = *tests[i].ifindex; ++ bpf_obj->bss->ret = 0; ++ err = bpf_prog_test_run_opts(bpf_program__fd(prog), &tattr); ++ sprintf(buf, "err: %s [%s]", tests[i].msg, bpf_program__name(prog)); ++ ++ if (at_tc && tests[i].success_on_tc) ++ ASSERT_GE(err, 0, buf); ++ else ++ ASSERT_EQ(err, tests[i].err, buf); ++ sprintf(buf, "ret: %s [%s]", tests[i].msg, bpf_program__name(prog)); ++ if (at_tc && tests[i].success_on_tc) ++ ASSERT_GE(bpf_obj->bss->ret, 0, buf); ++ else ++ ASSERT_EQ(bpf_obj->bss->ret, tests[i].ret, buf); ++ } ++ } ++ ++out: ++ if (bpf_obj) ++ empty_skb__destroy(bpf_obj); ++ if (tok) ++ close_netns(tok); ++ system("ip netns del empty_skb"); ++} +diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c +index a4b4133d39e95..0d82e28aed1ac 100644 +--- a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c ++++ b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c +@@ -325,7 +325,7 @@ static bool symbol_equal(const void *key1, const void *key2, void *ctx __maybe_u + static int get_syms(char ***symsp, size_t *cntp) + { + size_t cap = 0, cnt = 0, i; +- char *name, **syms = NULL; ++ char *name = NULL, **syms = NULL; + struct hashmap *map; + char buf[256]; + FILE *f; +@@ -352,6 +352,8 @@ static int get_syms(char ***symsp, size_t *cntp) + /* skip modules */ + if (strchr(buf, '[')) + continue; ++ ++ free(name); + if (sscanf(buf, "%ms$*[^\n]\n", &name) != 1) + continue; + /* +@@ -371,32 +373,32 @@ static int get_syms(char ***symsp, size_t *cntp) + if (!strncmp(name, "__ftrace_invalid_address__", + sizeof("__ftrace_invalid_address__") - 1)) + continue; ++ + err = hashmap__add(map, name, NULL); +- if (err) { +- free(name); +- if (err == -EEXIST) +- continue; ++ if (err == -EEXIST) ++ continue; ++ if (err) + goto error; +- } ++ + err = libbpf_ensure_mem((void **) &syms, &cap, + sizeof(*syms), cnt + 1); +- if (err) { +- free(name); ++ if (err) + goto error; +- } +- syms[cnt] = name; +- cnt++; ++ ++ syms[cnt++] = name; ++ name = NULL; + } + + *symsp = syms; + *cntp = cnt; + + error: ++ free(name); + fclose(f); + hashmap__free(map); + if (err) { + for (i = 0; i < cnt; i++) +- free(syms[cnt]); ++ free(syms[i]); + free(syms); + } + return err; +diff --git a/tools/testing/selftests/bpf/prog_tests/lsm_cgroup.c b/tools/testing/selftests/bpf/prog_tests/lsm_cgroup.c +index 1102e4f42d2d4..f117bfef68a14 100644 +--- a/tools/testing/selftests/bpf/prog_tests/lsm_cgroup.c ++++ b/tools/testing/selftests/bpf/prog_tests/lsm_cgroup.c +@@ -173,10 +173,12 @@ static void test_lsm_cgroup_functional(void) + ASSERT_EQ(query_prog_cnt(cgroup_fd, NULL), 4, "total prog count"); + ASSERT_EQ(query_prog_cnt(cgroup_fd2, NULL), 1, "total prog count"); + +- /* AF_UNIX is prohibited. */ +- + fd = socket(AF_UNIX, SOCK_STREAM, 0); +- ASSERT_LT(fd, 0, "socket(AF_UNIX)"); ++ if (!(skel->kconfig->CONFIG_SECURITY_APPARMOR ++ || skel->kconfig->CONFIG_SECURITY_SELINUX ++ || skel->kconfig->CONFIG_SECURITY_SMACK)) ++ /* AF_UNIX is prohibited. */ ++ ASSERT_LT(fd, 0, "socket(AF_UNIX)"); + close(fd); + + /* AF_INET6 gets default policy (sk_priority). */ +@@ -233,11 +235,18 @@ static void test_lsm_cgroup_functional(void) + + /* AF_INET6+SOCK_STREAM + * AF_PACKET+SOCK_RAW ++ * AF_UNIX+SOCK_RAW if already have non-bpf lsms installed + * listen_fd + * client_fd + * accepted_fd + */ +- ASSERT_EQ(skel->bss->called_socket_post_create2, 5, "called_create2"); ++ if (skel->kconfig->CONFIG_SECURITY_APPARMOR ++ || skel->kconfig->CONFIG_SECURITY_SELINUX ++ || skel->kconfig->CONFIG_SECURITY_SMACK) ++ /* AF_UNIX+SOCK_RAW if already have non-bpf lsms installed */ ++ ASSERT_EQ(skel->bss->called_socket_post_create2, 6, "called_create2"); ++ else ++ ASSERT_EQ(skel->bss->called_socket_post_create2, 5, "called_create2"); + + /* start_server + * bind(ETH_P_ALL) +diff --git a/tools/testing/selftests/bpf/prog_tests/map_kptr.c b/tools/testing/selftests/bpf/prog_tests/map_kptr.c +index fdcea7a61491e..0d66b15242089 100644 +--- a/tools/testing/selftests/bpf/prog_tests/map_kptr.c ++++ b/tools/testing/selftests/bpf/prog_tests/map_kptr.c +@@ -105,7 +105,7 @@ static void test_map_kptr_success(bool test_run) + ASSERT_OK(opts.retval, "test_map_kptr_ref2 retval"); + + if (test_run) +- return; ++ goto exit; + + ret = bpf_map__update_elem(skel->maps.array_map, + &key, sizeof(key), buf, sizeof(buf), 0); +@@ -132,6 +132,7 @@ static void test_map_kptr_success(bool test_run) + ret = bpf_map__delete_elem(skel->maps.lru_hash_map, &key, sizeof(key), 0); + ASSERT_OK(ret, "lru_hash_map delete"); + ++exit: + map_kptr__destroy(skel); + } + +diff --git a/tools/testing/selftests/bpf/prog_tests/tcp_hdr_options.c b/tools/testing/selftests/bpf/prog_tests/tcp_hdr_options.c +index 617bbce6ef8f1..57191773572a0 100644 +--- a/tools/testing/selftests/bpf/prog_tests/tcp_hdr_options.c ++++ b/tools/testing/selftests/bpf/prog_tests/tcp_hdr_options.c +@@ -485,7 +485,7 @@ static void misc(void) + goto check_linum; + + ret = read(sk_fds.passive_fd, recv_msg, sizeof(recv_msg)); +- if (ASSERT_EQ(ret, sizeof(send_msg), "read(msg)")) ++ if (!ASSERT_EQ(ret, sizeof(send_msg), "read(msg)")) + goto check_linum; + } + +@@ -539,7 +539,7 @@ void test_tcp_hdr_options(void) + goto skel_destroy; + + cg_fd = test__join_cgroup(CG_NAME); +- if (ASSERT_GE(cg_fd, 0, "join_cgroup")) ++ if (!ASSERT_GE(cg_fd, 0, "join_cgroup")) + goto skel_destroy; + + for (i = 0; i < ARRAY_SIZE(tests); i++) { +diff --git a/tools/testing/selftests/bpf/prog_tests/tracing_struct.c b/tools/testing/selftests/bpf/prog_tests/tracing_struct.c +index d5022b91d1e4c..48dc9472e160a 100644 +--- a/tools/testing/selftests/bpf/prog_tests/tracing_struct.c ++++ b/tools/testing/selftests/bpf/prog_tests/tracing_struct.c +@@ -15,7 +15,7 @@ static void test_fentry(void) + + err = tracing_struct__attach(skel); + if (!ASSERT_OK(err, "tracing_struct__attach")) +- return; ++ goto destroy_skel; + + ASSERT_OK(trigger_module_test_read(256), "trigger_read"); + +@@ -54,6 +54,7 @@ static void test_fentry(void) + ASSERT_EQ(skel->bss->t5_ret, 1, "t5 ret"); + + tracing_struct__detach(skel); ++destroy_skel: + tracing_struct__destroy(skel); + } + +diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c b/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c +index 9b9cf8458adf8..39973ea1ce433 100644 +--- a/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c ++++ b/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c +@@ -18,7 +18,7 @@ static void test_xdp_adjust_tail_shrink(void) + ); + + err = bpf_prog_test_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd); +- if (ASSERT_OK(err, "test_xdp_adjust_tail_shrink")) ++ if (!ASSERT_OK(err, "test_xdp_adjust_tail_shrink")) + return; + + err = bpf_prog_test_run_opts(prog_fd, &topts); +@@ -53,7 +53,7 @@ static void test_xdp_adjust_tail_grow(void) + ); + + err = bpf_prog_test_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd); +- if (ASSERT_OK(err, "test_xdp_adjust_tail_grow")) ++ if (!ASSERT_OK(err, "test_xdp_adjust_tail_grow")) + return; + + err = bpf_prog_test_run_opts(prog_fd, &topts); +@@ -63,6 +63,7 @@ static void test_xdp_adjust_tail_grow(void) + expect_sz = sizeof(pkt_v6) + 40; /* Test grow with 40 bytes */ + topts.data_in = &pkt_v6; + topts.data_size_in = sizeof(pkt_v6); ++ topts.data_size_out = sizeof(buf); + err = bpf_prog_test_run_opts(prog_fd, &topts); + ASSERT_OK(err, "ipv6"); + ASSERT_EQ(topts.retval, XDP_TX, "ipv6 retval"); +@@ -89,7 +90,7 @@ static void test_xdp_adjust_tail_grow2(void) + ); + + err = bpf_prog_test_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd); +- if (ASSERT_OK(err, "test_xdp_adjust_tail_grow")) ++ if (!ASSERT_OK(err, "test_xdp_adjust_tail_grow")) + return; + + /* Test case-64 */ +diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c b/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c +index a50971c6cf4a5..9ac6f6a268db2 100644 +--- a/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c ++++ b/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c +@@ -85,7 +85,7 @@ static void test_max_pkt_size(int fd) + } + + #define NUM_PKTS 10000 +-void test_xdp_do_redirect(void) ++void serial_test_xdp_do_redirect(void) + { + int err, xdp_prog_fd, tc_prog_fd, ifindex_src, ifindex_dst; + char data[sizeof(pkt_udp) + sizeof(__u32)]; +diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_synproxy.c b/tools/testing/selftests/bpf/prog_tests/xdp_synproxy.c +index 75550a40e029d..879f5da2f21e6 100644 +--- a/tools/testing/selftests/bpf/prog_tests/xdp_synproxy.c ++++ b/tools/testing/selftests/bpf/prog_tests/xdp_synproxy.c +@@ -174,7 +174,7 @@ out: + system("ip netns del synproxy"); + } + +-void test_xdp_synproxy(void) ++void serial_test_xdp_synproxy(void) + { + if (test__start_subtest("xdp")) + test_synproxy(true); +diff --git a/tools/testing/selftests/bpf/progs/bpf_iter_ksym.c b/tools/testing/selftests/bpf/progs/bpf_iter_ksym.c +index 285c008cbf9c2..9ba14c37bbcc9 100644 +--- a/tools/testing/selftests/bpf/progs/bpf_iter_ksym.c ++++ b/tools/testing/selftests/bpf/progs/bpf_iter_ksym.c +@@ -7,14 +7,14 @@ char _license[] SEC("license") = "GPL"; + + unsigned long last_sym_value = 0; + +-static inline char tolower(char c) ++static inline char to_lower(char c) + { + if (c >= 'A' && c <= 'Z') + c += ('a' - 'A'); + return c; + } + +-static inline char toupper(char c) ++static inline char to_upper(char c) + { + if (c >= 'a' && c <= 'z') + c -= ('a' - 'A'); +@@ -54,7 +54,7 @@ int dump_ksym(struct bpf_iter__ksym *ctx) + type = iter->type; + + if (iter->module_name[0]) { +- type = iter->exported ? toupper(type) : tolower(type); ++ type = iter->exported ? to_upper(type) : to_lower(type); + BPF_SEQ_PRINTF(seq, "0x%llx %c %s [ %s ] ", + value, type, iter->name, iter->module_name); + } else { +diff --git a/tools/testing/selftests/bpf/progs/empty_skb.c b/tools/testing/selftests/bpf/progs/empty_skb.c +new file mode 100644 +index 0000000000000..4b0cd67532511 +--- /dev/null ++++ b/tools/testing/selftests/bpf/progs/empty_skb.c +@@ -0,0 +1,37 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++#include <linux/bpf.h> ++#include <bpf/bpf_helpers.h> ++#include <bpf/bpf_endian.h> ++ ++char _license[] SEC("license") = "GPL"; ++ ++int ifindex; ++int ret; ++ ++SEC("lwt_xmit") ++int redirect_ingress(struct __sk_buff *skb) ++{ ++ ret = bpf_clone_redirect(skb, ifindex, BPF_F_INGRESS); ++ return 0; ++} ++ ++SEC("lwt_xmit") ++int redirect_egress(struct __sk_buff *skb) ++{ ++ ret = bpf_clone_redirect(skb, ifindex, 0); ++ return 0; ++} ++ ++SEC("tc") ++int tc_redirect_ingress(struct __sk_buff *skb) ++{ ++ ret = bpf_clone_redirect(skb, ifindex, BPF_F_INGRESS); ++ return 0; ++} ++ ++SEC("tc") ++int tc_redirect_egress(struct __sk_buff *skb) ++{ ++ ret = bpf_clone_redirect(skb, ifindex, 0); ++ return 0; ++} +diff --git a/tools/testing/selftests/bpf/progs/lsm_cgroup.c b/tools/testing/selftests/bpf/progs/lsm_cgroup.c +index 4f2d60b87b75d..02c11d16b692a 100644 +--- a/tools/testing/selftests/bpf/progs/lsm_cgroup.c ++++ b/tools/testing/selftests/bpf/progs/lsm_cgroup.c +@@ -7,6 +7,10 @@ + + char _license[] SEC("license") = "GPL"; + ++extern bool CONFIG_SECURITY_SELINUX __kconfig __weak; ++extern bool CONFIG_SECURITY_SMACK __kconfig __weak; ++extern bool CONFIG_SECURITY_APPARMOR __kconfig __weak; ++ + #ifndef AF_PACKET + #define AF_PACKET 17 + #endif +@@ -140,6 +144,10 @@ SEC("lsm_cgroup/sk_alloc_security") + int BPF_PROG(socket_alloc, struct sock *sk, int family, gfp_t priority) + { + called_socket_alloc++; ++ /* if already have non-bpf lsms installed, EPERM will cause memory leak of non-bpf lsms */ ++ if (CONFIG_SECURITY_SELINUX || CONFIG_SECURITY_SMACK || CONFIG_SECURITY_APPARMOR) ++ return 1; ++ + if (family == AF_UNIX) + return 0; /* EPERM */ + +diff --git a/tools/testing/selftests/bpf/test_bpftool_metadata.sh b/tools/testing/selftests/bpf/test_bpftool_metadata.sh +index 1bf81b49457af..b5520692f41bd 100755 +--- a/tools/testing/selftests/bpf/test_bpftool_metadata.sh ++++ b/tools/testing/selftests/bpf/test_bpftool_metadata.sh +@@ -4,6 +4,9 @@ + # Kselftest framework requirement - SKIP code is 4. + ksft_skip=4 + ++BPF_FILE_USED="metadata_used.bpf.o" ++BPF_FILE_UNUSED="metadata_unused.bpf.o" ++ + TESTNAME=bpftool_metadata + BPF_FS=$(awk '$3 == "bpf" {print $2; exit}' /proc/mounts) + BPF_DIR=$BPF_FS/test_$TESTNAME +@@ -55,7 +58,7 @@ mkdir $BPF_DIR + + trap cleanup EXIT + +-bpftool prog load metadata_unused.o $BPF_DIR/unused ++bpftool prog load $BPF_FILE_UNUSED $BPF_DIR/unused + + METADATA_PLAIN="$(bpftool prog)" + echo "$METADATA_PLAIN" | grep 'a = "foo"' > /dev/null +@@ -67,7 +70,7 @@ bpftool map | grep 'metadata.rodata' > /dev/null + + rm $BPF_DIR/unused + +-bpftool prog load metadata_used.o $BPF_DIR/used ++bpftool prog load $BPF_FILE_USED $BPF_DIR/used + + METADATA_PLAIN="$(bpftool prog)" + echo "$METADATA_PLAIN" | grep 'a = "bar"' > /dev/null +diff --git a/tools/testing/selftests/bpf/test_flow_dissector.sh b/tools/testing/selftests/bpf/test_flow_dissector.sh +index 5303ce0c977bd..4b298863797a2 100755 +--- a/tools/testing/selftests/bpf/test_flow_dissector.sh ++++ b/tools/testing/selftests/bpf/test_flow_dissector.sh +@@ -2,6 +2,8 @@ + # SPDX-License-Identifier: GPL-2.0 + # + # Load BPF flow dissector and verify it correctly dissects traffic ++ ++BPF_FILE="bpf_flow.bpf.o" + export TESTNAME=test_flow_dissector + unmount=0 + +@@ -22,7 +24,7 @@ if [[ -z $(ip netns identify $$) ]]; then + if bpftool="$(which bpftool)"; then + echo "Testing global flow dissector..." + +- $bpftool prog loadall ./bpf_flow.o /sys/fs/bpf/flow \ ++ $bpftool prog loadall $BPF_FILE /sys/fs/bpf/flow \ + type flow_dissector + + if ! unshare --net $bpftool prog attach pinned \ +@@ -95,7 +97,7 @@ else + fi + + # Attach BPF program +-./flow_dissector_load -p bpf_flow.o -s _dissect ++./flow_dissector_load -p $BPF_FILE -s _dissect + + # Setup + tc qdisc add dev lo ingress +diff --git a/tools/testing/selftests/bpf/test_lwt_ip_encap.sh b/tools/testing/selftests/bpf/test_lwt_ip_encap.sh +index 6c69c42b1d607..1e565f47aca94 100755 +--- a/tools/testing/selftests/bpf/test_lwt_ip_encap.sh ++++ b/tools/testing/selftests/bpf/test_lwt_ip_encap.sh +@@ -38,6 +38,7 @@ + # ping: SRC->[encap at veth2:ingress]->GRE:decap->DST + # ping replies go DST->SRC directly + ++BPF_FILE="test_lwt_ip_encap.bpf.o" + if [[ $EUID -ne 0 ]]; then + echo "This script must be run as root" + echo "FAIL" +@@ -373,14 +374,14 @@ test_egress() + # install replacement routes (LWT/eBPF), pings succeed + if [ "${ENCAP}" == "IPv4" ] ; then + ip -netns ${NS1} route add ${IPv4_DST} encap bpf xmit obj \ +- test_lwt_ip_encap.o sec encap_gre dev veth1 ${VRF} ++ ${BPF_FILE} sec encap_gre dev veth1 ${VRF} + ip -netns ${NS1} -6 route add ${IPv6_DST} encap bpf xmit obj \ +- test_lwt_ip_encap.o sec encap_gre dev veth1 ${VRF} ++ ${BPF_FILE} sec encap_gre dev veth1 ${VRF} + elif [ "${ENCAP}" == "IPv6" ] ; then + ip -netns ${NS1} route add ${IPv4_DST} encap bpf xmit obj \ +- test_lwt_ip_encap.o sec encap_gre6 dev veth1 ${VRF} ++ ${BPF_FILE} sec encap_gre6 dev veth1 ${VRF} + ip -netns ${NS1} -6 route add ${IPv6_DST} encap bpf xmit obj \ +- test_lwt_ip_encap.o sec encap_gre6 dev veth1 ${VRF} ++ ${BPF_FILE} sec encap_gre6 dev veth1 ${VRF} + else + echo " unknown encap ${ENCAP}" + TEST_STATUS=1 +@@ -431,14 +432,14 @@ test_ingress() + # install replacement routes (LWT/eBPF), pings succeed + if [ "${ENCAP}" == "IPv4" ] ; then + ip -netns ${NS2} route add ${IPv4_DST} encap bpf in obj \ +- test_lwt_ip_encap.o sec encap_gre dev veth2 ${VRF} ++ ${BPF_FILE} sec encap_gre dev veth2 ${VRF} + ip -netns ${NS2} -6 route add ${IPv6_DST} encap bpf in obj \ +- test_lwt_ip_encap.o sec encap_gre dev veth2 ${VRF} ++ ${BPF_FILE} sec encap_gre dev veth2 ${VRF} + elif [ "${ENCAP}" == "IPv6" ] ; then + ip -netns ${NS2} route add ${IPv4_DST} encap bpf in obj \ +- test_lwt_ip_encap.o sec encap_gre6 dev veth2 ${VRF} ++ ${BPF_FILE} sec encap_gre6 dev veth2 ${VRF} + ip -netns ${NS2} -6 route add ${IPv6_DST} encap bpf in obj \ +- test_lwt_ip_encap.o sec encap_gre6 dev veth2 ${VRF} ++ ${BPF_FILE} sec encap_gre6 dev veth2 ${VRF} + else + echo "FAIL: unknown encap ${ENCAP}" + TEST_STATUS=1 +diff --git a/tools/testing/selftests/bpf/test_lwt_seg6local.sh b/tools/testing/selftests/bpf/test_lwt_seg6local.sh +index 826f4423ce029..0efea2292d6aa 100755 +--- a/tools/testing/selftests/bpf/test_lwt_seg6local.sh ++++ b/tools/testing/selftests/bpf/test_lwt_seg6local.sh +@@ -23,6 +23,7 @@ + + # Kselftest framework requirement - SKIP code is 4. + ksft_skip=4 ++BPF_FILE="test_lwt_seg6local.bpf.o" + readonly NS1="ns1-$(mktemp -u XXXXXX)" + readonly NS2="ns2-$(mktemp -u XXXXXX)" + readonly NS3="ns3-$(mktemp -u XXXXXX)" +@@ -117,18 +118,18 @@ ip netns exec ${NS6} ip -6 addr add fb00::109/16 dev veth10 scope link + ip netns exec ${NS1} ip -6 addr add fb00::1/16 dev lo + ip netns exec ${NS1} ip -6 route add fb00::6 dev veth1 via fb00::21 + +-ip netns exec ${NS2} ip -6 route add fb00::6 encap bpf in obj test_lwt_seg6local.o sec encap_srh dev veth2 ++ip netns exec ${NS2} ip -6 route add fb00::6 encap bpf in obj ${BPF_FILE} sec encap_srh dev veth2 + ip netns exec ${NS2} ip -6 route add fd00::1 dev veth3 via fb00::43 scope link + + ip netns exec ${NS3} ip -6 route add fc42::1 dev veth5 via fb00::65 +-ip netns exec ${NS3} ip -6 route add fd00::1 encap seg6local action End.BPF endpoint obj test_lwt_seg6local.o sec add_egr_x dev veth4 ++ip netns exec ${NS3} ip -6 route add fd00::1 encap seg6local action End.BPF endpoint obj ${BPF_FILE} sec add_egr_x dev veth4 + +-ip netns exec ${NS4} ip -6 route add fd00::2 encap seg6local action End.BPF endpoint obj test_lwt_seg6local.o sec pop_egr dev veth6 ++ip netns exec ${NS4} ip -6 route add fd00::2 encap seg6local action End.BPF endpoint obj ${BPF_FILE} sec pop_egr dev veth6 + ip netns exec ${NS4} ip -6 addr add fc42::1 dev lo + ip netns exec ${NS4} ip -6 route add fd00::3 dev veth7 via fb00::87 + + ip netns exec ${NS5} ip -6 route add fd00::4 table 117 dev veth9 via fb00::109 +-ip netns exec ${NS5} ip -6 route add fd00::3 encap seg6local action End.BPF endpoint obj test_lwt_seg6local.o sec inspect_t dev veth8 ++ip netns exec ${NS5} ip -6 route add fd00::3 encap seg6local action End.BPF endpoint obj ${BPF_FILE} sec inspect_t dev veth8 + + ip netns exec ${NS6} ip -6 addr add fb00::6/16 dev lo + ip netns exec ${NS6} ip -6 addr add fd00::4/16 dev lo +diff --git a/tools/testing/selftests/bpf/test_tc_edt.sh b/tools/testing/selftests/bpf/test_tc_edt.sh +index daa7d1b8d3092..76f0bd17061f9 100755 +--- a/tools/testing/selftests/bpf/test_tc_edt.sh ++++ b/tools/testing/selftests/bpf/test_tc_edt.sh +@@ -5,6 +5,7 @@ + # with dst port = 9000 down to 5MBps. Then it measures actual + # throughput of the flow. + ++BPF_FILE="test_tc_edt.bpf.o" + if [[ $EUID -ne 0 ]]; then + echo "This script must be run as root" + echo "FAIL" +@@ -54,7 +55,7 @@ ip -netns ${NS_DST} route add ${IP_SRC}/32 dev veth_dst + ip netns exec ${NS_SRC} tc qdisc add dev veth_src root fq + ip netns exec ${NS_SRC} tc qdisc add dev veth_src clsact + ip netns exec ${NS_SRC} tc filter add dev veth_src egress \ +- bpf da obj test_tc_edt.o sec cls_test ++ bpf da obj ${BPF_FILE} sec cls_test + + + # start the listener +diff --git a/tools/testing/selftests/bpf/test_tc_tunnel.sh b/tools/testing/selftests/bpf/test_tc_tunnel.sh +index 088fcad138c98..334bdfeab9403 100755 +--- a/tools/testing/selftests/bpf/test_tc_tunnel.sh ++++ b/tools/testing/selftests/bpf/test_tc_tunnel.sh +@@ -3,6 +3,7 @@ + # + # In-place tunneling + ++BPF_FILE="test_tc_tunnel.bpf.o" + # must match the port that the bpf program filters on + readonly port=8000 + +@@ -196,7 +197,7 @@ verify_data + # client can no longer connect + ip netns exec "${ns1}" tc qdisc add dev veth1 clsact + ip netns exec "${ns1}" tc filter add dev veth1 egress \ +- bpf direct-action object-file ./test_tc_tunnel.o \ ++ bpf direct-action object-file ${BPF_FILE} \ + section "encap_${tuntype}_${mac}" + echo "test bpf encap without decap (expect failure)" + server_listen +@@ -296,7 +297,7 @@ fi + ip netns exec "${ns2}" ip link del dev testtun0 + ip netns exec "${ns2}" tc qdisc add dev veth2 clsact + ip netns exec "${ns2}" tc filter add dev veth2 ingress \ +- bpf direct-action object-file ./test_tc_tunnel.o section decap ++ bpf direct-action object-file ${BPF_FILE} section decap + echo "test bpf encap with bpf decap" + client_connect + verify_data +diff --git a/tools/testing/selftests/bpf/test_tunnel.sh b/tools/testing/selftests/bpf/test_tunnel.sh +index e9ebc67d73f70..2eaedc1d9ed30 100755 +--- a/tools/testing/selftests/bpf/test_tunnel.sh ++++ b/tools/testing/selftests/bpf/test_tunnel.sh +@@ -45,6 +45,7 @@ + # 5) Tunnel protocol handler, ex: vxlan_rcv, decap the packet + # 6) Forward the packet to the overlay tnl dev + ++BPF_FILE="test_tunnel_kern.bpf.o" + BPF_PIN_TUNNEL_DIR="/sys/fs/bpf/tc/tunnel" + PING_ARG="-c 3 -w 10 -q" + ret=0 +@@ -545,7 +546,7 @@ test_xfrm_tunnel() + > /sys/kernel/debug/tracing/trace + setup_xfrm_tunnel + mkdir -p ${BPF_PIN_TUNNEL_DIR} +- bpftool prog loadall ./test_tunnel_kern.o ${BPF_PIN_TUNNEL_DIR} ++ bpftool prog loadall ${BPF_FILE} ${BPF_PIN_TUNNEL_DIR} + tc qdisc add dev veth1 clsact + tc filter add dev veth1 proto ip ingress bpf da object-pinned \ + ${BPF_PIN_TUNNEL_DIR}/xfrm_get_state +@@ -572,7 +573,7 @@ attach_bpf() + SET=$2 + GET=$3 + mkdir -p ${BPF_PIN_TUNNEL_DIR} +- bpftool prog loadall ./test_tunnel_kern.o ${BPF_PIN_TUNNEL_DIR}/ ++ bpftool prog loadall ${BPF_FILE} ${BPF_PIN_TUNNEL_DIR}/ + tc qdisc add dev $DEV clsact + tc filter add dev $DEV egress bpf da object-pinned ${BPF_PIN_TUNNEL_DIR}/$SET + tc filter add dev $DEV ingress bpf da object-pinned ${BPF_PIN_TUNNEL_DIR}/$GET +diff --git a/tools/testing/selftests/bpf/test_xdp_meta.sh b/tools/testing/selftests/bpf/test_xdp_meta.sh +index ea69370caae30..2740322c1878b 100755 +--- a/tools/testing/selftests/bpf/test_xdp_meta.sh ++++ b/tools/testing/selftests/bpf/test_xdp_meta.sh +@@ -1,5 +1,6 @@ + #!/bin/sh + ++BPF_FILE="test_xdp_meta.bpf.o" + # Kselftest framework requirement - SKIP code is 4. + readonly KSFT_SKIP=4 + readonly NS1="ns1-$(mktemp -u XXXXXX)" +@@ -42,11 +43,11 @@ ip netns exec ${NS2} ip addr add 10.1.1.22/24 dev veth2 + ip netns exec ${NS1} tc qdisc add dev veth1 clsact + ip netns exec ${NS2} tc qdisc add dev veth2 clsact + +-ip netns exec ${NS1} tc filter add dev veth1 ingress bpf da obj test_xdp_meta.o sec t +-ip netns exec ${NS2} tc filter add dev veth2 ingress bpf da obj test_xdp_meta.o sec t ++ip netns exec ${NS1} tc filter add dev veth1 ingress bpf da obj ${BPF_FILE} sec t ++ip netns exec ${NS2} tc filter add dev veth2 ingress bpf da obj ${BPF_FILE} sec t + +-ip netns exec ${NS1} ip link set dev veth1 xdp obj test_xdp_meta.o sec x +-ip netns exec ${NS2} ip link set dev veth2 xdp obj test_xdp_meta.o sec x ++ip netns exec ${NS1} ip link set dev veth1 xdp obj ${BPF_FILE} sec x ++ip netns exec ${NS2} ip link set dev veth2 xdp obj ${BPF_FILE} sec x + + ip netns exec ${NS1} ip link set dev veth1 up + ip netns exec ${NS2} ip link set dev veth2 up +diff --git a/tools/testing/selftests/bpf/test_xdp_vlan.sh b/tools/testing/selftests/bpf/test_xdp_vlan.sh +index 810c407e0286e..fbcaa9f0120b2 100755 +--- a/tools/testing/selftests/bpf/test_xdp_vlan.sh ++++ b/tools/testing/selftests/bpf/test_xdp_vlan.sh +@@ -200,11 +200,11 @@ ip netns exec ${NS2} sh -c 'ping -W 1 -c 1 100.64.41.1 || echo "Success: First p + # ---------------------------------------------------------------------- + # In ns1: ingress use XDP to remove VLAN tags + export DEVNS1=veth1 +-export FILE=test_xdp_vlan.o ++export BPF_FILE=test_xdp_vlan.bpf.o + + # First test: Remove VLAN by setting VLAN ID 0, using "xdp_vlan_change" + export XDP_PROG=xdp_vlan_change +-ip netns exec ${NS1} ip link set $DEVNS1 $XDP_MODE object $FILE section $XDP_PROG ++ip netns exec ${NS1} ip link set $DEVNS1 $XDP_MODE object $BPF_FILE section $XDP_PROG + + # In ns1: egress use TC to add back VLAN tag 4011 + # (del cmd) +@@ -212,7 +212,7 @@ ip netns exec ${NS1} ip link set $DEVNS1 $XDP_MODE object $FILE section $XDP_PRO + # + ip netns exec ${NS1} tc qdisc add dev $DEVNS1 clsact + ip netns exec ${NS1} tc filter add dev $DEVNS1 egress \ +- prio 1 handle 1 bpf da obj $FILE sec tc_vlan_push ++ prio 1 handle 1 bpf da obj $BPF_FILE sec tc_vlan_push + + # Now the namespaces can reach each-other, test with ping: + ip netns exec ${NS2} ping -i 0.2 -W 2 -c 2 $IPADDR1 +@@ -226,7 +226,7 @@ ip netns exec ${NS1} ping -i 0.2 -W 2 -c 2 $IPADDR2 + # + export XDP_PROG=xdp_vlan_remove_outer2 + ip netns exec ${NS1} ip link set $DEVNS1 $XDP_MODE off +-ip netns exec ${NS1} ip link set $DEVNS1 $XDP_MODE object $FILE section $XDP_PROG ++ip netns exec ${NS1} ip link set $DEVNS1 $XDP_MODE object $BPF_FILE section $XDP_PROG + + # Now the namespaces should still be able reach each-other, test with ping: + ip netns exec ${NS2} ping -i 0.2 -W 2 -c 2 $IPADDR1 +diff --git a/tools/testing/selftests/bpf/xdp_synproxy.c b/tools/testing/selftests/bpf/xdp_synproxy.c +index ff35320d2be97..410a1385a01dd 100644 +--- a/tools/testing/selftests/bpf/xdp_synproxy.c ++++ b/tools/testing/selftests/bpf/xdp_synproxy.c +@@ -104,7 +104,8 @@ static void parse_options(int argc, char *argv[], unsigned int *ifindex, __u32 * + { "tc", no_argument, NULL, 'c' }, + { NULL, 0, NULL, 0 }, + }; +- unsigned long mss4, mss6, wscale, ttl; ++ unsigned long mss4, wscale, ttl; ++ unsigned long long mss6; + unsigned int tcpipopts_mask = 0; + + if (argc < 2) +@@ -286,7 +287,7 @@ static int syncookie_open_bpf_maps(__u32 prog_id, int *values_map_fd, int *ports + + prog_info = (struct bpf_prog_info) { + .nr_map_ids = 8, +- .map_ids = (__u64)map_ids, ++ .map_ids = (__u64)(unsigned long)map_ids, + }; + info_len = sizeof(prog_info); + +diff --git a/tools/testing/selftests/cgroup/cgroup_util.c b/tools/testing/selftests/cgroup/cgroup_util.c +index 4c52cc6f2f9cc..e8bbbdb77e0d5 100644 +--- a/tools/testing/selftests/cgroup/cgroup_util.c ++++ b/tools/testing/selftests/cgroup/cgroup_util.c +@@ -555,6 +555,7 @@ int proc_mount_contains(const char *option) + ssize_t proc_read_text(int pid, bool thread, const char *item, char *buf, size_t size) + { + char path[PATH_MAX]; ++ ssize_t ret; + + if (!pid) + snprintf(path, sizeof(path), "/proc/%s/%s", +@@ -562,8 +563,8 @@ ssize_t proc_read_text(int pid, bool thread, const char *item, char *buf, size_t + else + snprintf(path, sizeof(path), "/proc/%d/%s", pid, item); + +- size = read_text(path, buf, size); +- return size < 0 ? -1 : size; ++ ret = read_text(path, buf, size); ++ return ret < 0 ? -1 : ret; + } + + int proc_read_strstr(int pid, bool thread, const char *item, const char *needle) +diff --git a/tools/testing/selftests/drivers/net/netdevsim/devlink.sh b/tools/testing/selftests/drivers/net/netdevsim/devlink.sh +index 9de1d123f4f5d..a08c02abde121 100755 +--- a/tools/testing/selftests/drivers/net/netdevsim/devlink.sh ++++ b/tools/testing/selftests/drivers/net/netdevsim/devlink.sh +@@ -496,8 +496,8 @@ dummy_reporter_test() + + check_reporter_info dummy healthy 3 3 10 true + +- echo 8192> $DEBUGFS_DIR/health/binary_len +- check_fail $? "Failed set dummy reporter binary len to 8192" ++ echo 8192 > $DEBUGFS_DIR/health/binary_len ++ check_err $? "Failed set dummy reporter binary len to 8192" + + local dump=$(devlink health dump show $DL_HANDLE reporter dummy -j) + check_err $? "Failed show dump of dummy reporter" +diff --git a/tools/testing/selftests/efivarfs/efivarfs.sh b/tools/testing/selftests/efivarfs/efivarfs.sh +index a90f394f9aa90..d374878cc0ba9 100755 +--- a/tools/testing/selftests/efivarfs/efivarfs.sh ++++ b/tools/testing/selftests/efivarfs/efivarfs.sh +@@ -87,6 +87,11 @@ test_create_read() + { + local file=$efivarfs_mount/$FUNCNAME-$test_guid + ./create-read $file ++ if [ $? -ne 0 ]; then ++ echo "create and read $file failed" ++ file_cleanup $file ++ exit 1 ++ fi + file_cleanup $file + } + +diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc +index 8d26d5505808b..3eea2abf68f9e 100644 +--- a/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc ++++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc +@@ -38,11 +38,18 @@ cnt_trace() { + + test_event_enabled() { + val=$1 ++ check_times=10 # wait for 10 * SLEEP_TIME at most + +- e=`cat $EVENT_ENABLE` +- if [ "$e" != $val ]; then +- fail "Expected $val but found $e" +- fi ++ while [ $check_times -ne 0 ]; do ++ e=`cat $EVENT_ENABLE` ++ if [ "$e" == $val ]; then ++ return 0 ++ fi ++ sleep $SLEEP_TIME ++ check_times=$((check_times - 1)) ++ done ++ ++ fail "Expected $val but found $e" + } + + run_enable_disable() { +diff --git a/tools/testing/selftests/netfilter/conntrack_icmp_related.sh b/tools/testing/selftests/netfilter/conntrack_icmp_related.sh +index b48e1833bc896..76645aaf2b58f 100755 +--- a/tools/testing/selftests/netfilter/conntrack_icmp_related.sh ++++ b/tools/testing/selftests/netfilter/conntrack_icmp_related.sh +@@ -35,6 +35,8 @@ cleanup() { + for i in 1 2;do ip netns del nsrouter$i;done + } + ++trap cleanup EXIT ++ + ipv4() { + echo -n 192.168.$1.2 + } +@@ -146,11 +148,17 @@ ip netns exec nsclient1 nft -f - <<EOF + table inet filter { + counter unknown { } + counter related { } ++ counter redir4 { } ++ counter redir6 { } + chain input { + type filter hook input priority 0; policy accept; +- meta l4proto { icmp, icmpv6 } ct state established,untracked accept + ++ icmp type "redirect" ct state "related" counter name "redir4" accept ++ icmpv6 type "nd-redirect" ct state "related" counter name "redir6" accept ++ ++ meta l4proto { icmp, icmpv6 } ct state established,untracked accept + meta l4proto { icmp, icmpv6 } ct state "related" counter name "related" accept ++ + counter name "unknown" drop + } + } +@@ -279,5 +287,29 @@ else + echo "ERROR: icmp error RELATED state test has failed" + fi + +-cleanup ++# add 'bad' route, expect icmp REDIRECT to be generated ++ip netns exec nsclient1 ip route add 192.168.1.42 via 192.168.1.1 ++ip netns exec nsclient1 ip route add dead:1::42 via dead:1::1 ++ ++ip netns exec "nsclient1" ping -q -c 2 192.168.1.42 > /dev/null ++ ++expect="packets 1 bytes 112" ++check_counter nsclient1 "redir4" "$expect" ++if [ $? -ne 0 ];then ++ ret=1 ++fi ++ ++ip netns exec "nsclient1" ping -c 1 dead:1::42 > /dev/null ++expect="packets 1 bytes 192" ++check_counter nsclient1 "redir6" "$expect" ++if [ $? -ne 0 ];then ++ ret=1 ++fi ++ ++if [ $ret -eq 0 ];then ++ echo "PASS: icmp redirects had RELATED state" ++else ++ echo "ERROR: icmp redirect RELATED state test has failed" ++fi ++ + exit $ret +diff --git a/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c b/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c +index fbbdffdb2e5d2..f20d1c166d1e4 100644 +--- a/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c ++++ b/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c +@@ -24,6 +24,7 @@ static int check_cpu_dscr_default(char *file, unsigned long val) + rc = read(fd, buf, sizeof(buf)); + if (rc == -1) { + perror("read() failed"); ++ close(fd); + return 1; + } + close(fd); +@@ -65,8 +66,10 @@ static int check_all_cpu_dscr_defaults(unsigned long val) + if (access(file, F_OK)) + continue; + +- if (check_cpu_dscr_default(file, val)) ++ if (check_cpu_dscr_default(file, val)) { ++ closedir(sysfs); + return 1; ++ } + } + closedir(sysfs); + return 0; +diff --git a/tools/testing/selftests/proc/proc-uptime-002.c b/tools/testing/selftests/proc/proc-uptime-002.c +index e7ceabed7f51f..7d0aa22bdc12b 100644 +--- a/tools/testing/selftests/proc/proc-uptime-002.c ++++ b/tools/testing/selftests/proc/proc-uptime-002.c +@@ -17,6 +17,7 @@ + // while shifting across CPUs. + #undef NDEBUG + #include <assert.h> ++#include <errno.h> + #include <unistd.h> + #include <sys/syscall.h> + #include <stdlib.h> +@@ -54,7 +55,7 @@ int main(void) + len += sizeof(unsigned long); + free(m); + m = malloc(len); +- } while (sys_sched_getaffinity(0, len, m) == -EINVAL); ++ } while (sys_sched_getaffinity(0, len, m) == -1 && errno == EINVAL); + + fd = open("/proc/uptime", O_RDONLY); + assert(fd >= 0); |