diff options
author | Mike Pagano <mpagano@gentoo.org> | 2022-08-17 10:32:06 -0400 |
---|---|---|
committer | Mike Pagano <mpagano@gentoo.org> | 2022-08-17 10:32:06 -0400 |
commit | 86706d28e7cd7d5f8ea3bef5964fe031c1c03df0 (patch) | |
tree | 2b3bcccb84650d244ff63eb17930868cc0ea42b2 | |
parent | Linux patch 5.15.60 (diff) | |
download | linux-patches-86706d28e7cd7d5f8ea3bef5964fe031c1c03df0.tar.gz linux-patches-86706d28e7cd7d5f8ea3bef5964fe031c1c03df0.tar.bz2 linux-patches-86706d28e7cd7d5f8ea3bef5964fe031c1c03df0.zip |
Linux patch 5.15.615.15-65
Signed-off-by: Mike Pagano <mpagano@gentoo.org>
-rw-r--r-- | 0000_README | 4 | ||||
-rw-r--r-- | 1060_linux-5.15.61.patch | 42556 |
2 files changed, 42560 insertions, 0 deletions
diff --git a/0000_README b/0000_README index a6bf4af4..ab98b89d 100644 --- a/0000_README +++ b/0000_README @@ -283,6 +283,10 @@ Patch: 1059_linux-5.15.60.patch From: http://www.kernel.org Desc: Linux 5.15.60 +Patch: 1060_linux-5.15.61.patch +From: http://www.kernel.org +Desc: Linux 5.15.61 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1060_linux-5.15.61.patch b/1060_linux-5.15.61.patch new file mode 100644 index 00000000..25ca0396 --- /dev/null +++ b/1060_linux-5.15.61.patch @@ -0,0 +1,42556 @@ +diff --git a/Documentation/ABI/testing/sysfs-driver-xen-blkback b/Documentation/ABI/testing/sysfs-driver-xen-blkback +index ac2947b989504..3d5de44cbbee9 100644 +--- a/Documentation/ABI/testing/sysfs-driver-xen-blkback ++++ b/Documentation/ABI/testing/sysfs-driver-xen-blkback +@@ -42,5 +42,5 @@ KernelVersion: 5.10 + Contact: SeongJae Park <sjpark@amazon.de> + Description: + Whether to enable the persistent grants feature or not. Note +- that this option only takes effect on newly created backends. ++ that this option only takes effect on newly connected backends. + The default is Y (enable). +diff --git a/Documentation/ABI/testing/sysfs-driver-xen-blkfront b/Documentation/ABI/testing/sysfs-driver-xen-blkfront +index 28008905615f0..1f7659aa085c2 100644 +--- a/Documentation/ABI/testing/sysfs-driver-xen-blkfront ++++ b/Documentation/ABI/testing/sysfs-driver-xen-blkfront +@@ -15,5 +15,5 @@ KernelVersion: 5.10 + Contact: SeongJae Park <sjpark@amazon.de> + Description: + Whether to enable the persistent grants feature or not. Note +- that this option only takes effect on newly created frontends. ++ that this option only takes effect on newly connected frontends. + The default is Y (enable). +diff --git a/Documentation/admin-guide/device-mapper/writecache.rst b/Documentation/admin-guide/device-mapper/writecache.rst +index 10429779a91ab..724e028d1858b 100644 +--- a/Documentation/admin-guide/device-mapper/writecache.rst ++++ b/Documentation/admin-guide/device-mapper/writecache.rst +@@ -78,16 +78,16 @@ Status: + 2. the number of blocks + 3. the number of free blocks + 4. the number of blocks under writeback +-5. the number of read requests +-6. the number of read requests that hit the cache +-7. the number of write requests +-8. the number of write requests that hit uncommitted block +-9. the number of write requests that hit committed block +-10. the number of write requests that bypass the cache +-11. the number of write requests that are allocated in the cache ++5. the number of read blocks ++6. the number of read blocks that hit the cache ++7. the number of write blocks ++8. the number of write blocks that hit uncommitted block ++9. the number of write blocks that hit committed block ++10. the number of write blocks that bypass the cache ++11. the number of write blocks that are allocated in the cache + 12. the number of write requests that are blocked on the freelist + 13. the number of flush requests +-14. the number of discard requests ++14. the number of discarded blocks + + Messages: + flush +diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt +index b47905c4a92fd..bcb102c91b190 100644 +--- a/Documentation/admin-guide/kernel-parameters.txt ++++ b/Documentation/admin-guide/kernel-parameters.txt +@@ -4974,20 +4974,33 @@ + Speculative Code Execution with Return Instructions) + vulnerability. + ++ AMD-based UNRET and IBPB mitigations alone do not stop ++ sibling threads from influencing the predictions of other ++ sibling threads. For that reason, STIBP is used on pro- ++ cessors that support it, and mitigate SMT on processors ++ that don't. ++ + off - no mitigation + auto - automatically select a migitation + auto,nosmt - automatically select a mitigation, + disabling SMT if necessary for + the full mitigation (only on Zen1 + and older without STIBP). +- ibpb - mitigate short speculation windows on +- basic block boundaries too. Safe, highest +- perf impact. +- unret - force enable untrained return thunks, +- only effective on AMD f15h-f17h +- based systems. +- unret,nosmt - like unret, will disable SMT when STIBP +- is not available. ++ ibpb - On AMD, mitigate short speculation ++ windows on basic block boundaries too. ++ Safe, highest perf impact. It also ++ enables STIBP if present. Not suitable ++ on Intel. ++ ibpb,nosmt - Like "ibpb" above but will disable SMT ++ when STIBP is not available. This is ++ the alternative for systems which do not ++ have STIBP. ++ unret - Force enable untrained return thunks, ++ only effective on AMD f15h-f17h based ++ systems. ++ unret,nosmt - Like unret, but will disable SMT when STIBP ++ is not available. This is the alternative for ++ systems which do not have STIBP. + + Selecting 'auto' will choose a mitigation method at run + time according to the CPU. +diff --git a/Documentation/admin-guide/pm/cpuidle.rst b/Documentation/admin-guide/pm/cpuidle.rst +index aec2cd2aaea73..19754beb5a4e6 100644 +--- a/Documentation/admin-guide/pm/cpuidle.rst ++++ b/Documentation/admin-guide/pm/cpuidle.rst +@@ -612,8 +612,8 @@ the ``menu`` governor to be used on the systems that use the ``ladder`` governor + by default this way, for example. + + The other kernel command line parameters controlling CPU idle time management +-described below are only relevant for the *x86* architecture and some of +-them affect Intel processors only. ++described below are only relevant for the *x86* architecture and references ++to ``intel_idle`` affect Intel processors only. + + The *x86* architecture support code recognizes three kernel command line + options related to CPU idle time management: ``idle=poll``, ``idle=halt``, +@@ -635,10 +635,13 @@ idle, so it very well may hurt single-thread computations performance as well as + energy-efficiency. Thus using it for performance reasons may not be a good idea + at all.] + +-The ``idle=nomwait`` option disables the ``intel_idle`` driver and causes +-``acpi_idle`` to be used (as long as all of the information needed by it is +-there in the system's ACPI tables), but it is not allowed to use the +-``MWAIT`` instruction of the CPUs to ask the hardware to enter idle states. ++The ``idle=nomwait`` option prevents the use of ``MWAIT`` instruction of ++the CPU to enter idle states. When this option is used, the ``acpi_idle`` ++driver will use the ``HLT`` instruction instead of ``MWAIT``. On systems ++running Intel processors, this option disables the ``intel_idle`` driver ++and forces the use of the ``acpi_idle`` driver instead. Note that in either ++case, ``acpi_idle`` driver will function only if all the information needed ++by it is in the system's ACPI tables. + + In addition to the architecture-level kernel command line options affecting CPU + idle time management, there are parameters affecting individual ``CPUIdle`` +diff --git a/Documentation/devicetree/bindings/iio/accel/adi,adxl355.yaml b/Documentation/devicetree/bindings/iio/accel/adi,adxl355.yaml +new file mode 100644 +index 0000000000000..ba54d6998f2ee +--- /dev/null ++++ b/Documentation/devicetree/bindings/iio/accel/adi,adxl355.yaml +@@ -0,0 +1,88 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/iio/accel/adi,adxl355.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Analog Devices ADXL355 3-Axis, Low noise MEMS Accelerometer ++ ++maintainers: ++ - Puranjay Mohan <puranjay12@gmail.com> ++ ++description: | ++ Analog Devices ADXL355 3-Axis, Low noise MEMS Accelerometer that supports ++ both I2C & SPI interfaces ++ https://www.analog.com/en/products/adxl355.html ++ ++properties: ++ compatible: ++ enum: ++ - adi,adxl355 ++ ++ reg: ++ maxItems: 1 ++ ++ interrupts: ++ minItems: 1 ++ maxItems: 3 ++ description: | ++ Type for DRDY should be IRQ_TYPE_EDGE_RISING. ++ Three configurable interrupt lines exist. ++ ++ interrupt-names: ++ description: Specify which interrupt line is in use. ++ items: ++ enum: ++ - INT1 ++ - INT2 ++ - DRDY ++ minItems: 1 ++ maxItems: 3 ++ ++ vdd-supply: ++ description: Regulator that provides power to the sensor ++ ++ vddio-supply: ++ description: Regulator that provides power to the bus ++ ++ spi-max-frequency: true ++ ++required: ++ - compatible ++ - reg ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include <dt-bindings/gpio/gpio.h> ++ #include <dt-bindings/interrupt-controller/irq.h> ++ i2c { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* Example for a I2C device node */ ++ accelerometer@1d { ++ compatible = "adi,adxl355"; ++ reg = <0x1d>; ++ interrupt-parent = <&gpio>; ++ interrupts = <25 IRQ_TYPE_EDGE_RISING>; ++ interrupt-names = "DRDY"; ++ }; ++ }; ++ - | ++ #include <dt-bindings/gpio/gpio.h> ++ #include <dt-bindings/interrupt-controller/irq.h> ++ spi { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ accelerometer@0 { ++ compatible = "adi,adxl355"; ++ reg = <0>; ++ spi-max-frequency = <1000000>; ++ interrupt-parent = <&gpio>; ++ interrupts = <25 IRQ_TYPE_EDGE_RISING>; ++ interrupt-names = "DRDY"; ++ }; ++ }; +diff --git a/Documentation/devicetree/bindings/riscv/sifive-l2-cache.yaml b/Documentation/devicetree/bindings/riscv/sifive-l2-cache.yaml +index 2b1f916038972..b72ec404adcd7 100644 +--- a/Documentation/devicetree/bindings/riscv/sifive-l2-cache.yaml ++++ b/Documentation/devicetree/bindings/riscv/sifive-l2-cache.yaml +@@ -47,7 +47,7 @@ properties: + const: 2 + + cache-sets: +- const: 1024 ++ enum: [1024, 2048] + + cache-size: + const: 2097152 +@@ -85,6 +85,8 @@ then: + description: | + Must contain entries for DirError, DataError and DataFail signals. + maxItems: 3 ++ cache-sets: ++ const: 1024 + + else: + properties: +@@ -92,6 +94,8 @@ else: + description: | + Must contain entries for DirError, DataError, DataFail, DirFail signals. + minItems: 4 ++ cache-sets: ++ const: 2048 + + additionalProperties: false + +diff --git a/Documentation/tty/device_drivers/oxsemi-tornado.rst b/Documentation/tty/device_drivers/oxsemi-tornado.rst +new file mode 100644 +index 0000000000000..0180d8bb08818 +--- /dev/null ++++ b/Documentation/tty/device_drivers/oxsemi-tornado.rst +@@ -0,0 +1,129 @@ ++.. SPDX-License-Identifier: GPL-2.0 ++ ++==================================================================== ++Notes on Oxford Semiconductor PCIe (Tornado) 950 serial port devices ++==================================================================== ++ ++Oxford Semiconductor PCIe (Tornado) 950 serial port devices are driven ++by a fixed 62.5MHz clock input derived from the 100MHz PCI Express clock. ++ ++The baud rate produced by the baud generator is obtained from this input ++frequency by dividing it by the clock prescaler, which can be set to any ++value from 1 to 63.875 in increments of 0.125, and then the usual 16-bit ++divisor is used as with the original 8250, to divide the frequency by a ++value from 1 to 65535. Finally a programmable oversampling rate is used ++that can take any value from 4 to 16 to divide the frequency further and ++determine the actual baud rate used. Baud rates from 15625000bps down ++to 0.933bps can be obtained this way. ++ ++By default the oversampling rate is set to 16 and the clock prescaler is ++set to 33.875, meaning that the frequency to be used as the reference ++for the usual 16-bit divisor is 115313.653, which is close enough to the ++frequency of 115200 used by the original 8250 for the same values to be ++used for the divisor to obtain the requested baud rates by software that ++is unaware of the extra clock controls available. ++ ++The oversampling rate is programmed with the TCR register and the clock ++prescaler is programmed with the CPR/CPR2 register pair[1][2][3][4]. ++To switch away from the default value of 33.875 for the prescaler the ++the enhanced mode has to be explicitly enabled though, by setting bit 4 ++of the EFR. In that mode setting bit 7 in the MCR enables the prescaler ++or otherwise it is bypassed as if the value of 1 was used. Additionally ++writing any value to CPR clears CPR2 for compatibility with old software ++written for older conventional PCI Oxford Semiconductor devices that do ++not have the extra prescaler's 9th bit in CPR2, so the CPR/CPR2 register ++pair has to be programmed in the right order. ++ ++By using these parameters rates from 15625000bps down to 1bps can be ++obtained, with either exact or highly-accurate actual bit rates for ++standard and many non-standard rates. ++ ++Here are the figures for the standard and some non-standard baud rates ++(including those quoted in Oxford Semiconductor documentation), giving ++the requested rate (r), the actual rate yielded (a) and its deviation ++from the requested rate (d), and the values of the oversampling rate ++(tcr), the clock prescaler (cpr) and the divisor (div) produced by the ++new `get_divisor' handler: ++ ++r: 15625000, a: 15625000.00, d: 0.0000%, tcr: 4, cpr: 1.000, div: 1 ++r: 12500000, a: 12500000.00, d: 0.0000%, tcr: 5, cpr: 1.000, div: 1 ++r: 10416666, a: 10416666.67, d: 0.0000%, tcr: 6, cpr: 1.000, div: 1 ++r: 8928571, a: 8928571.43, d: 0.0000%, tcr: 7, cpr: 1.000, div: 1 ++r: 7812500, a: 7812500.00, d: 0.0000%, tcr: 8, cpr: 1.000, div: 1 ++r: 4000000, a: 4000000.00, d: 0.0000%, tcr: 5, cpr: 3.125, div: 1 ++r: 3686400, a: 3676470.59, d: -0.2694%, tcr: 8, cpr: 2.125, div: 1 ++r: 3500000, a: 3496503.50, d: -0.0999%, tcr: 13, cpr: 1.375, div: 1 ++r: 3000000, a: 2976190.48, d: -0.7937%, tcr: 14, cpr: 1.500, div: 1 ++r: 2500000, a: 2500000.00, d: 0.0000%, tcr: 10, cpr: 2.500, div: 1 ++r: 2000000, a: 2000000.00, d: 0.0000%, tcr: 10, cpr: 3.125, div: 1 ++r: 1843200, a: 1838235.29, d: -0.2694%, tcr: 16, cpr: 2.125, div: 1 ++r: 1500000, a: 1492537.31, d: -0.4975%, tcr: 5, cpr: 8.375, div: 1 ++r: 1152000, a: 1152073.73, d: 0.0064%, tcr: 14, cpr: 3.875, div: 1 ++r: 921600, a: 919117.65, d: -0.2694%, tcr: 16, cpr: 2.125, div: 2 ++r: 576000, a: 576036.87, d: 0.0064%, tcr: 14, cpr: 3.875, div: 2 ++r: 460800, a: 460829.49, d: 0.0064%, tcr: 7, cpr: 3.875, div: 5 ++r: 230400, a: 230414.75, d: 0.0064%, tcr: 14, cpr: 3.875, div: 5 ++r: 115200, a: 115207.37, d: 0.0064%, tcr: 14, cpr: 1.250, div: 31 ++r: 57600, a: 57603.69, d: 0.0064%, tcr: 8, cpr: 3.875, div: 35 ++r: 38400, a: 38402.46, d: 0.0064%, tcr: 14, cpr: 3.875, div: 30 ++r: 19200, a: 19201.23, d: 0.0064%, tcr: 8, cpr: 3.875, div: 105 ++r: 9600, a: 9600.06, d: 0.0006%, tcr: 9, cpr: 1.125, div: 643 ++r: 4800, a: 4799.98, d: -0.0004%, tcr: 7, cpr: 2.875, div: 647 ++r: 2400, a: 2400.02, d: 0.0008%, tcr: 9, cpr: 2.250, div: 1286 ++r: 1200, a: 1200.00, d: 0.0000%, tcr: 14, cpr: 2.875, div: 1294 ++r: 300, a: 300.00, d: 0.0000%, tcr: 11, cpr: 2.625, div: 7215 ++r: 200, a: 200.00, d: 0.0000%, tcr: 16, cpr: 1.250, div: 15625 ++r: 150, a: 150.00, d: 0.0000%, tcr: 13, cpr: 2.250, div: 14245 ++r: 134, a: 134.00, d: 0.0000%, tcr: 11, cpr: 2.625, div: 16153 ++r: 110, a: 110.00, d: 0.0000%, tcr: 12, cpr: 1.000, div: 47348 ++r: 75, a: 75.00, d: 0.0000%, tcr: 4, cpr: 5.875, div: 35461 ++r: 50, a: 50.00, d: 0.0000%, tcr: 16, cpr: 1.250, div: 62500 ++r: 25, a: 25.00, d: 0.0000%, tcr: 16, cpr: 2.500, div: 62500 ++r: 4, a: 4.00, d: 0.0000%, tcr: 16, cpr: 20.000, div: 48828 ++r: 2, a: 2.00, d: 0.0000%, tcr: 16, cpr: 40.000, div: 48828 ++r: 1, a: 1.00, d: 0.0000%, tcr: 16, cpr: 63.875, div: 61154 ++ ++With the baud base set to 15625000 and the unsigned 16-bit UART_DIV_MAX ++limitation imposed by `serial8250_get_baud_rate' standard baud rates ++below 300bps become unavailable in the regular way, e.g. the rate of ++200bps requires the baud base to be divided by 78125 and that is beyond ++the unsigned 16-bit range. The historic spd_cust feature can still be ++used by encoding the values for, the prescaler, the oversampling rate ++and the clock divisor (DLM/DLL) as follows to obtain such rates if so ++required: ++ ++ 31 29 28 20 19 16 15 0 +++-----+-----------------+-------+-------------------------------+ ++|0 0 0| CPR2:CPR | TCR | DLM:DLL | +++-----+-----------------+-------+-------------------------------+ ++ ++Use a value such encoded for the `custom_divisor' field along with the ++ASYNC_SPD_CUST flag set in the `flags' field in `struct serial_struct' ++passed with the TIOCSSERIAL ioctl(2), such as with the setserial(8) ++utility and its `divisor' and `spd_cust' parameters, and the select ++the baud rate of 38400bps. Note that the value of 0 in TCR sets the ++oversampling rate to 16 and prescaler values below 1 in CPR2/CPR are ++clamped by the driver to 1. ++ ++For example the value of 0x1f4004e2 will set CPR2/CPR, TCR and DLM/DLL ++respectively to 0x1f4, 0x0 and 0x04e2, choosing the prescaler value, ++the oversampling rate and the clock divisor of 62.500, 16 and 1250 ++respectively. These parameters will set the baud rate for the serial ++port to 62500000 / 62.500 / 1250 / 16 = 50bps. ++ ++References: ++ ++[1] "OXPCIe200 PCI Express Multi-Port Bridge", Oxford Semiconductor, ++ Inc., DS-0045, 10 Nov 2008, Section "950 Mode", pp. 64-65 ++ ++[2] "OXPCIe952 PCI Express Bridge to Dual Serial & Parallel Port", ++ Oxford Semiconductor, Inc., DS-0046, Mar 06 08, Section "950 Mode", ++ p. 20 ++ ++[3] "OXPCIe954 PCI Express Bridge to Quad Serial Port", Oxford ++ Semiconductor, Inc., DS-0047, Feb 08, Section "950 Mode", p. 20 ++ ++[4] "OXPCIe958 PCI Express Bridge to Octal Serial Port", Oxford ++ Semiconductor, Inc., DS-0048, Feb 08, Section "950 Mode", p. 20 ++ ++Maciej W. Rozycki <macro@orcam.me.uk> +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +index 976d34445a246..f1421cf1a1b31 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +@@ -3326,15 +3326,15 @@ enum v4l2_mpeg_video_hevc_size_of_length_field - + * - __u8 + - ``poc_st_curr_before[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` + - PocStCurrBefore as described in section 8.3.2 "Decoding process for reference +- picture set. ++ picture set": provides the index of the short term before references in DPB array. + * - __u8 + - ``poc_st_curr_after[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` + - PocStCurrAfter as described in section 8.3.2 "Decoding process for reference +- picture set. ++ picture set": provides the index of the short term after references in DPB array. + * - __u8 + - ``poc_lt_curr[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` + - PocLtCurr as described in section 8.3.2 "Decoding process for reference +- picture set. ++ picture set": provides the index of the long term references in DPB array. + * - __u64 + - ``flags`` + - See :ref:`Decode Parameters Flags <hevc_decode_params_flags>` +diff --git a/Makefile b/Makefile +index 4ea646f496c9c..0802acf352d2b 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 5 + PATCHLEVEL = 15 +-SUBLEVEL = 60 ++SUBLEVEL = 61 + EXTRAVERSION = + NAME = Trick or Treat + +@@ -1078,6 +1078,11 @@ KBUILD_CFLAGS += $(KCFLAGS) + KBUILD_LDFLAGS_MODULE += --build-id=sha1 + LDFLAGS_vmlinux += --build-id=sha1 + ++KBUILD_LDFLAGS += -z noexecstack ++ifeq ($(CONFIG_LD_IS_BFD),y) ++KBUILD_LDFLAGS += $(call ld-option,--no-warn-rwx-segments) ++endif ++ + ifeq ($(CONFIG_STRIP_ASM_SYMS),y) + LDFLAGS_vmlinux += $(call ld-option, -X,) + endif +diff --git a/arch/Kconfig b/arch/Kconfig +index 191589f26b1a8..5987363b41c28 100644 +--- a/arch/Kconfig ++++ b/arch/Kconfig +@@ -200,6 +200,9 @@ config HAVE_NMI + config TRACE_IRQFLAGS_SUPPORT + bool + ++config TRACE_IRQFLAGS_NMI_SUPPORT ++ bool ++ + # + # An arch should select this if it provides all these things: + # +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index 27ca1ca6e827c..7a72fc636a7a7 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -127,6 +127,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm47094-luxul-xwr-3150-v1.dtb \ + bcm47094-netgear-r8500.dtb \ + bcm47094-phicomm-k3.dtb \ ++ bcm53015-meraki-mr26.dtb \ + bcm53016-meraki-mr32.dtb \ + bcm94708.dtb \ + bcm94709.dtb \ +diff --git a/arch/arm/boot/dts/aspeed-ast2500-evb.dts b/arch/arm/boot/dts/aspeed-ast2500-evb.dts +index 1d24b394ea4c3..a497dd135491b 100644 +--- a/arch/arm/boot/dts/aspeed-ast2500-evb.dts ++++ b/arch/arm/boot/dts/aspeed-ast2500-evb.dts +@@ -5,7 +5,7 @@ + + / { + model = "AST2500 EVB"; +- compatible = "aspeed,ast2500"; ++ compatible = "aspeed,ast2500-evb", "aspeed,ast2500"; + + aliases { + serial4 = &uart5; +diff --git a/arch/arm/boot/dts/aspeed-ast2600-evb-a1.dts b/arch/arm/boot/dts/aspeed-ast2600-evb-a1.dts +index dd7148060c4a3..d0a5c2ff0fec4 100644 +--- a/arch/arm/boot/dts/aspeed-ast2600-evb-a1.dts ++++ b/arch/arm/boot/dts/aspeed-ast2600-evb-a1.dts +@@ -5,6 +5,7 @@ + + / { + model = "AST2600 A1 EVB"; ++ compatible = "aspeed,ast2600-evb-a1", "aspeed,ast2600"; + + /delete-node/regulator-vcc-sdhci0; + /delete-node/regulator-vcc-sdhci1; +diff --git a/arch/arm/boot/dts/aspeed-ast2600-evb.dts b/arch/arm/boot/dts/aspeed-ast2600-evb.dts +index 788448cdd6b3f..b8e55bf167aa8 100644 +--- a/arch/arm/boot/dts/aspeed-ast2600-evb.dts ++++ b/arch/arm/boot/dts/aspeed-ast2600-evb.dts +@@ -8,7 +8,7 @@ + + / { + model = "AST2600 EVB"; +- compatible = "aspeed,ast2600"; ++ compatible = "aspeed,ast2600-evb-a1", "aspeed,ast2600"; + + aliases { + serial4 = &uart5; +diff --git a/arch/arm/boot/dts/bcm53015-meraki-mr26.dts b/arch/arm/boot/dts/bcm53015-meraki-mr26.dts +new file mode 100644 +index 0000000000000..14f58033efeb9 +--- /dev/null ++++ b/arch/arm/boot/dts/bcm53015-meraki-mr26.dts +@@ -0,0 +1,166 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++/* ++ * Broadcom BCM470X / BCM5301X ARM platform code. ++ * DTS for Meraki MR26 / Codename: Venom ++ * ++ * Copyright (C) 2022 Christian Lamparter <chunkeey@gmail.com> ++ */ ++ ++/dts-v1/; ++ ++#include "bcm4708.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" ++#include <dt-bindings/leds/common.h> ++ ++/ { ++ compatible = "meraki,mr26", "brcm,bcm53015", "brcm,bcm4708"; ++ model = "Meraki MR26"; ++ ++ memory@0 { ++ reg = <0x00000000 0x08000000>; ++ device_type = "memory"; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-0 { ++ function = LED_FUNCTION_FAULT; ++ color = <LED_COLOR_ID_AMBER>; ++ gpios = <&chipcommon 13 GPIO_ACTIVE_HIGH>; ++ panic-indicator; ++ }; ++ led-1 { ++ function = LED_FUNCTION_INDICATOR; ++ color = <LED_COLOR_ID_WHITE>; ++ gpios = <&chipcommon 12 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ ++ keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ key-restart { ++ label = "Reset"; ++ linux,code = <KEY_RESTART>; ++ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&uart0 { ++ clock-frequency = <50000000>; ++ /delete-property/ clocks; ++}; ++ ++&uart1 { ++ status = "disabled"; ++}; ++ ++&gmac0 { ++ status = "okay"; ++}; ++ ++&gmac1 { ++ status = "disabled"; ++}; ++&gmac2 { ++ status = "disabled"; ++}; ++&gmac3 { ++ status = "disabled"; ++}; ++ ++&nandcs { ++ nand-ecc-algo = "hw"; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ ++ partition@0 { ++ label = "u-boot"; ++ reg = <0x0 0x200000>; ++ read-only; ++ }; ++ ++ partition@200000 { ++ label = "u-boot-env"; ++ reg = <0x200000 0x200000>; ++ /* empty */ ++ }; ++ ++ partition@400000 { ++ label = "u-boot-backup"; ++ reg = <0x400000 0x200000>; ++ /* empty */ ++ }; ++ ++ partition@600000 { ++ label = "u-boot-env-backup"; ++ reg = <0x600000 0x200000>; ++ /* empty */ ++ }; ++ ++ partition@800000 { ++ label = "ubi"; ++ reg = <0x800000 0x7780000>; ++ }; ++ }; ++}; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ reg = <0>; ++ label = "poe"; ++ }; ++ ++ port@5 { ++ reg = <5>; ++ label = "cpu"; ++ ethernet = <&gmac0>; ++ ++ fixed-link { ++ speed = <1000>; ++ duplex-full; ++ }; ++ }; ++ }; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinmux_i2c>; ++ ++ clock-frequency = <100000>; ++ ++ ina219@40 { ++ compatible = "ti,ina219"; /* PoE power */ ++ reg = <0x40>; ++ shunt-resistor = <60000>; /* = 60 mOhms */ ++ }; ++ ++ eeprom@56 { ++ compatible = "atmel,24c64"; ++ reg = <0x56>; ++ pagesize = <32>; ++ read-only; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ /* it's empty */ ++ }; ++}; ++ ++&thermal { ++ status = "disabled"; ++ /* does not work, reads 418 degree Celsius */ ++}; +diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi +index afeec01f65228..eca8bf89ab88f 100644 +--- a/arch/arm/boot/dts/imx6ul.dtsi ++++ b/arch/arm/boot/dts/imx6ul.dtsi +@@ -64,20 +64,18 @@ + clock-frequency = <696000000>; + clock-latency = <61036>; /* two CLK32 periods */ + #cooling-cells = <2>; +- operating-points = < ++ operating-points = + /* kHz uV */ +- 696000 1275000 +- 528000 1175000 +- 396000 1025000 +- 198000 950000 +- >; +- fsl,soc-operating-points = < ++ <696000 1275000>, ++ <528000 1175000>, ++ <396000 1025000>, ++ <198000 950000>; ++ fsl,soc-operating-points = + /* KHz uV */ +- 696000 1275000 +- 528000 1175000 +- 396000 1175000 +- 198000 1175000 +- >; ++ <696000 1275000>, ++ <528000 1175000>, ++ <396000 1175000>, ++ <198000 1175000>; + clocks = <&clks IMX6UL_CLK_ARM>, + <&clks IMX6UL_CLK_PLL2_BUS>, + <&clks IMX6UL_CLK_PLL2_PFD2>, +@@ -149,6 +147,9 @@ + ocram: sram@900000 { + compatible = "mmio-sram"; + reg = <0x00900000 0x20000>; ++ ranges = <0 0x00900000 0x20000>; ++ #address-cells = <1>; ++ #size-cells = <1>; + }; + + intc: interrupt-controller@a01000 { +@@ -543,7 +544,7 @@ + }; + + kpp: keypad@20b8000 { +- compatible = "fsl,imx6ul-kpp", "fsl,imx6q-kpp", "fsl,imx21-kpp"; ++ compatible = "fsl,imx6ul-kpp", "fsl,imx21-kpp"; + reg = <0x020b8000 0x4000>; + interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6UL_CLK_KPP>; +@@ -998,7 +999,7 @@ + }; + + csi: csi@21c4000 { +- compatible = "fsl,imx6ul-csi", "fsl,imx7-csi"; ++ compatible = "fsl,imx6ul-csi"; + reg = <0x021c4000 0x4000>; + interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6UL_CLK_CSI>; +@@ -1007,7 +1008,7 @@ + }; + + lcdif: lcdif@21c8000 { +- compatible = "fsl,imx6ul-lcdif", "fsl,imx28-lcdif"; ++ compatible = "fsl,imx6ul-lcdif", "fsl,imx6sx-lcdif"; + reg = <0x021c8000 0x4000>; + interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6UL_CLK_LCDIF_PIX>, +@@ -1028,7 +1029,7 @@ + qspi: spi@21e0000 { + #address-cells = <1>; + #size-cells = <0>; +- compatible = "fsl,imx6ul-qspi", "fsl,imx6sx-qspi"; ++ compatible = "fsl,imx6ul-qspi"; + reg = <0x021e0000 0x4000>, <0x60000000 0x10000000>; + reg-names = "QuadSPI", "QuadSPI-memory"; + interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>; +diff --git a/arch/arm/boot/dts/imx7d-colibri-emmc.dtsi b/arch/arm/boot/dts/imx7d-colibri-emmc.dtsi +index af39e5370fa12..045e4413d3390 100644 +--- a/arch/arm/boot/dts/imx7d-colibri-emmc.dtsi ++++ b/arch/arm/boot/dts/imx7d-colibri-emmc.dtsi +@@ -13,6 +13,10 @@ + }; + }; + ++&cpu1 { ++ cpu-supply = <®_DCDC2>; ++}; ++ + &gpio6 { + gpio-line-names = "", + "", +diff --git a/arch/arm/boot/dts/qcom-mdm9615.dtsi b/arch/arm/boot/dts/qcom-mdm9615.dtsi +index dda2ceec6591a..ad9b52d53ef9b 100644 +--- a/arch/arm/boot/dts/qcom-mdm9615.dtsi ++++ b/arch/arm/boot/dts/qcom-mdm9615.dtsi +@@ -324,6 +324,7 @@ + + pmicgpio: gpio@150 { + compatible = "qcom,pm8018-gpio", "qcom,ssbi-gpio"; ++ reg = <0x150>; + interrupt-controller; + #interrupt-cells = <2>; + gpio-controller; +diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi +index 2b01bc29ddf23..05d51839d40a1 100644 +--- a/arch/arm/boot/dts/qcom-msm8974.dtsi ++++ b/arch/arm/boot/dts/qcom-msm8974.dtsi +@@ -718,7 +718,7 @@ + blsp2_uart7: serial@f995d000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0xf995d000 0x1000>; +- interrupts = <GIC_SPI 113 IRQ_TYPE_NONE>; ++ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gcc GCC_BLSP2_UART1_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>; + clock-names = "core", "iface"; + status = "disabled"; +diff --git a/arch/arm/boot/dts/qcom-pm8841.dtsi b/arch/arm/boot/dts/qcom-pm8841.dtsi +index 2fd59c440903d..c73e5b149ac5e 100644 +--- a/arch/arm/boot/dts/qcom-pm8841.dtsi ++++ b/arch/arm/boot/dts/qcom-pm8841.dtsi +@@ -25,6 +25,7 @@ + compatible = "qcom,spmi-temp-alarm"; + reg = <0x2400>; + interrupts = <4 0x24 0 IRQ_TYPE_EDGE_RISING>; ++ #thermal-sensor-cells = <0>; + }; + }; + +diff --git a/arch/arm/boot/dts/qcom-sdx55.dtsi b/arch/arm/boot/dts/qcom-sdx55.dtsi +index b5b784c5c65e4..0e76d03087fe5 100644 +--- a/arch/arm/boot/dts/qcom-sdx55.dtsi ++++ b/arch/arm/boot/dts/qcom-sdx55.dtsi +@@ -205,7 +205,7 @@ + blsp1_uart3: serial@831000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x00831000 0x200>; +- interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_LOW>; ++ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gcc 30>, + <&gcc 9>; + clock-names = "core", "iface"; +diff --git a/arch/arm/boot/dts/ste-ux500-samsung-codina.dts b/arch/arm/boot/dts/ste-ux500-samsung-codina.dts +index 952606e607ed6..ce62ba877da12 100644 +--- a/arch/arm/boot/dts/ste-ux500-samsung-codina.dts ++++ b/arch/arm/boot/dts/ste-ux500-samsung-codina.dts +@@ -544,8 +544,8 @@ + reg = <0x19>; + vdd-supply = <&ab8500_ldo_aux1_reg>; // 3V + vddio-supply = <&ab8500_ldo_aux2_reg>; // 1.8V +- mount-matrix = "0", "-1", "0", +- "1", "0", "0", ++ mount-matrix = "0", "1", "0", ++ "-1", "0", "0", + "0", "0", "1"; + }; + }; +diff --git a/arch/arm/boot/dts/ste-ux500-samsung-gavini.dts b/arch/arm/boot/dts/ste-ux500-samsung-gavini.dts +index fabc390ccb0cf..6c9e812ef03f4 100644 +--- a/arch/arm/boot/dts/ste-ux500-samsung-gavini.dts ++++ b/arch/arm/boot/dts/ste-ux500-samsung-gavini.dts +@@ -502,8 +502,8 @@ + accelerometer@18 { + compatible = "bosch,bma222e"; + reg = <0x18>; +- mount-matrix = "0", "1", "0", +- "-1", "0", "0", ++ mount-matrix = "0", "-1", "0", ++ "1", "0", "0", + "0", "0", "1"; + vddio-supply = <&ab8500_ldo_aux2_reg>; // 1.8V + vdd-supply = <&ab8500_ldo_aux1_reg>; // 3V +diff --git a/arch/arm/boot/dts/uniphier-pxs2.dtsi b/arch/arm/boot/dts/uniphier-pxs2.dtsi +index e81e5937a60ae..03301ddb3403a 100644 +--- a/arch/arm/boot/dts/uniphier-pxs2.dtsi ++++ b/arch/arm/boot/dts/uniphier-pxs2.dtsi +@@ -597,8 +597,8 @@ + compatible = "socionext,uniphier-dwc3", "snps,dwc3"; + status = "disabled"; + reg = <0x65a00000 0xcd00>; +- interrupt-names = "host", "peripheral"; +- interrupts = <0 134 4>, <0 135 4>; ++ interrupt-names = "dwc_usb3"; ++ interrupts = <0 134 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb0>, <&pinctrl_usb2>; + clock-names = "ref", "bus_early", "suspend"; +@@ -693,8 +693,8 @@ + compatible = "socionext,uniphier-dwc3", "snps,dwc3"; + status = "disabled"; + reg = <0x65c00000 0xcd00>; +- interrupt-names = "host", "peripheral"; +- interrupts = <0 137 4>, <0 138 4>; ++ interrupt-names = "dwc_usb3"; ++ interrupts = <0 137 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb1>, <&pinctrl_usb3>; + clock-names = "ref", "bus_early", "suspend"; +diff --git a/arch/arm/crypto/Kconfig b/arch/arm/crypto/Kconfig +index e4dba5461cb3e..149a5bd6b88c1 100644 +--- a/arch/arm/crypto/Kconfig ++++ b/arch/arm/crypto/Kconfig +@@ -63,7 +63,7 @@ config CRYPTO_SHA512_ARM + using optimized ARM assembler and NEON, when available. + + config CRYPTO_BLAKE2S_ARM +- tristate "BLAKE2s digest algorithm (ARM)" ++ bool "BLAKE2s digest algorithm (ARM)" + select CRYPTO_ARCH_HAVE_LIB_BLAKE2S + help + BLAKE2s digest algorithm optimized with ARM scalar instructions. This +diff --git a/arch/arm/crypto/Makefile b/arch/arm/crypto/Makefile +index 0274f81cc8ea0..971e74546fb1b 100644 +--- a/arch/arm/crypto/Makefile ++++ b/arch/arm/crypto/Makefile +@@ -9,8 +9,7 @@ obj-$(CONFIG_CRYPTO_SHA1_ARM) += sha1-arm.o + obj-$(CONFIG_CRYPTO_SHA1_ARM_NEON) += sha1-arm-neon.o + obj-$(CONFIG_CRYPTO_SHA256_ARM) += sha256-arm.o + obj-$(CONFIG_CRYPTO_SHA512_ARM) += sha512-arm.o +-obj-$(CONFIG_CRYPTO_BLAKE2S_ARM) += blake2s-arm.o +-obj-$(if $(CONFIG_CRYPTO_BLAKE2S_ARM),y) += libblake2s-arm.o ++obj-$(CONFIG_CRYPTO_BLAKE2S_ARM) += libblake2s-arm.o + obj-$(CONFIG_CRYPTO_BLAKE2B_NEON) += blake2b-neon.o + obj-$(CONFIG_CRYPTO_CHACHA20_NEON) += chacha-neon.o + obj-$(CONFIG_CRYPTO_POLY1305_ARM) += poly1305-arm.o +@@ -32,7 +31,6 @@ sha256-arm-neon-$(CONFIG_KERNEL_MODE_NEON) := sha256_neon_glue.o + sha256-arm-y := sha256-core.o sha256_glue.o $(sha256-arm-neon-y) + sha512-arm-neon-$(CONFIG_KERNEL_MODE_NEON) := sha512-neon-glue.o + sha512-arm-y := sha512-core.o sha512-glue.o $(sha512-arm-neon-y) +-blake2s-arm-y := blake2s-shash.o + libblake2s-arm-y:= blake2s-core.o blake2s-glue.o + blake2b-neon-y := blake2b-neon-core.o blake2b-neon-glue.o + sha1-arm-ce-y := sha1-ce-core.o sha1-ce-glue.o +diff --git a/arch/arm/crypto/blake2s-shash.c b/arch/arm/crypto/blake2s-shash.c +deleted file mode 100644 +index 763c73beea2d0..0000000000000 +--- a/arch/arm/crypto/blake2s-shash.c ++++ /dev/null +@@ -1,75 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later +-/* +- * BLAKE2s digest algorithm, ARM scalar implementation +- * +- * Copyright 2020 Google LLC +- */ +- +-#include <crypto/internal/blake2s.h> +-#include <crypto/internal/hash.h> +- +-#include <linux/module.h> +- +-static int crypto_blake2s_update_arm(struct shash_desc *desc, +- const u8 *in, unsigned int inlen) +-{ +- return crypto_blake2s_update(desc, in, inlen, false); +-} +- +-static int crypto_blake2s_final_arm(struct shash_desc *desc, u8 *out) +-{ +- return crypto_blake2s_final(desc, out, false); +-} +- +-#define BLAKE2S_ALG(name, driver_name, digest_size) \ +- { \ +- .base.cra_name = name, \ +- .base.cra_driver_name = driver_name, \ +- .base.cra_priority = 200, \ +- .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, \ +- .base.cra_blocksize = BLAKE2S_BLOCK_SIZE, \ +- .base.cra_ctxsize = sizeof(struct blake2s_tfm_ctx), \ +- .base.cra_module = THIS_MODULE, \ +- .digestsize = digest_size, \ +- .setkey = crypto_blake2s_setkey, \ +- .init = crypto_blake2s_init, \ +- .update = crypto_blake2s_update_arm, \ +- .final = crypto_blake2s_final_arm, \ +- .descsize = sizeof(struct blake2s_state), \ +- } +- +-static struct shash_alg blake2s_arm_algs[] = { +- BLAKE2S_ALG("blake2s-128", "blake2s-128-arm", BLAKE2S_128_HASH_SIZE), +- BLAKE2S_ALG("blake2s-160", "blake2s-160-arm", BLAKE2S_160_HASH_SIZE), +- BLAKE2S_ALG("blake2s-224", "blake2s-224-arm", BLAKE2S_224_HASH_SIZE), +- BLAKE2S_ALG("blake2s-256", "blake2s-256-arm", BLAKE2S_256_HASH_SIZE), +-}; +- +-static int __init blake2s_arm_mod_init(void) +-{ +- return IS_REACHABLE(CONFIG_CRYPTO_HASH) ? +- crypto_register_shashes(blake2s_arm_algs, +- ARRAY_SIZE(blake2s_arm_algs)) : 0; +-} +- +-static void __exit blake2s_arm_mod_exit(void) +-{ +- if (IS_REACHABLE(CONFIG_CRYPTO_HASH)) +- crypto_unregister_shashes(blake2s_arm_algs, +- ARRAY_SIZE(blake2s_arm_algs)); +-} +- +-module_init(blake2s_arm_mod_init); +-module_exit(blake2s_arm_mod_exit); +- +-MODULE_DESCRIPTION("BLAKE2s digest algorithm, ARM scalar implementation"); +-MODULE_LICENSE("GPL"); +-MODULE_AUTHOR("Eric Biggers <ebiggers@google.com>"); +-MODULE_ALIAS_CRYPTO("blake2s-128"); +-MODULE_ALIAS_CRYPTO("blake2s-128-arm"); +-MODULE_ALIAS_CRYPTO("blake2s-160"); +-MODULE_ALIAS_CRYPTO("blake2s-160-arm"); +-MODULE_ALIAS_CRYPTO("blake2s-224"); +-MODULE_ALIAS_CRYPTO("blake2s-224-arm"); +-MODULE_ALIAS_CRYPTO("blake2s-256"); +-MODULE_ALIAS_CRYPTO("blake2s-256-arm"); +diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S +index dfc6bfa430121..24486dad9e19b 100644 +--- a/arch/arm/include/asm/entry-macro-multi.S ++++ b/arch/arm/include/asm/entry-macro-multi.S +@@ -13,28 +13,4 @@ + @ + badrne lr, 1b + bne asm_do_IRQ +- +-#ifdef CONFIG_SMP +- /* +- * XXX +- * +- * this macro assumes that irqstat (r2) and base (r6) are +- * preserved from get_irqnr_and_base above +- */ +- ALT_SMP(test_for_ipi r0, r2, r6, lr) +- ALT_UP_B(9997f) +- movne r1, sp +- badrne lr, 1b +- bne do_IPI +-#endif +-9997: +- .endm +- +- .macro arch_irq_handler, symbol_name +- .align 5 +- .global \symbol_name +-\symbol_name: +- mov r8, lr +- arch_irq_handler_default +- ret r8 + .endm +diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h +index 5d508f5d56c49..fc11ddf13b8fd 100644 +--- a/arch/arm/include/asm/smp.h ++++ b/arch/arm/include/asm/smp.h +@@ -24,11 +24,6 @@ struct seq_file; + */ + extern void show_ipi_list(struct seq_file *, int); + +-/* +- * Called from assembly code, this handles an IPI. +- */ +-asmlinkage void do_IPI(int ipinr, struct pt_regs *regs); +- + /* + * Called from C code, this handles an IPI. + */ +diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c +index 842427ff2b3cb..23d369ab7e037 100644 +--- a/arch/arm/kernel/smp.c ++++ b/arch/arm/kernel/smp.c +@@ -622,11 +622,6 @@ static void ipi_complete(unsigned int cpu) + /* + * Main handler for inter-processor interrupts + */ +-asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs) +-{ +- handle_IPI(ipinr, regs); +-} +- + static void do_handle_IPI(int ipinr) + { + unsigned int cpu = smp_processor_id(); +diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S +index b5e8b9ae4c7d4..7fd3600db8efd 100644 +--- a/arch/arm/lib/findbit.S ++++ b/arch/arm/lib/findbit.S +@@ -40,8 +40,8 @@ ENDPROC(_find_first_zero_bit_le) + * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset) + */ + ENTRY(_find_next_zero_bit_le) +- teq r1, #0 +- beq 3b ++ cmp r2, r1 ++ bhs 3b + ands ip, r2, #7 + beq 1b @ If new byte, goto old routine + ARM( ldrb r3, [r0, r2, lsr #3] ) +@@ -81,8 +81,8 @@ ENDPROC(_find_first_bit_le) + * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset) + */ + ENTRY(_find_next_bit_le) +- teq r1, #0 +- beq 3b ++ cmp r2, r1 ++ bhs 3b + ands ip, r2, #7 + beq 1b @ If new byte, goto old routine + ARM( ldrb r3, [r0, r2, lsr #3] ) +@@ -115,8 +115,8 @@ ENTRY(_find_first_zero_bit_be) + ENDPROC(_find_first_zero_bit_be) + + ENTRY(_find_next_zero_bit_be) +- teq r1, #0 +- beq 3b ++ cmp r2, r1 ++ bhs 3b + ands ip, r2, #7 + beq 1b @ If new byte, goto old routine + eor r3, r2, #0x18 @ big endian byte ordering +@@ -149,8 +149,8 @@ ENTRY(_find_first_bit_be) + ENDPROC(_find_first_bit_be) + + ENTRY(_find_next_bit_be) +- teq r1, #0 +- beq 3b ++ cmp r2, r1 ++ bhs 3b + ands ip, r2, #7 + beq 1b @ If new byte, goto old routine + eor r3, r2, #0x18 @ big endian byte ordering +diff --git a/arch/arm/mach-bcm/bcm_kona_smc.c b/arch/arm/mach-bcm/bcm_kona_smc.c +index 43829e49ad93f..347bfb7f03e2c 100644 +--- a/arch/arm/mach-bcm/bcm_kona_smc.c ++++ b/arch/arm/mach-bcm/bcm_kona_smc.c +@@ -52,6 +52,7 @@ int __init bcm_kona_smc_init(void) + return -ENODEV; + + prop_val = of_get_address(node, 0, &prop_size, NULL); ++ of_node_put(node); + if (!prop_val) + return -EINVAL; + +diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c +index 21413a9b7b6c6..8d829f3dafe76 100644 +--- a/arch/arm/mach-omap2/display.c ++++ b/arch/arm/mach-omap2/display.c +@@ -211,6 +211,7 @@ static int __init omapdss_init_fbdev(void) + node = of_find_node_by_name(NULL, "omap4_padconf_global"); + if (node) + omap4_dsi_mux_syscon = syscon_node_to_regmap(node); ++ of_node_put(node); + + return 0; + } +@@ -259,11 +260,13 @@ static int __init omapdss_init_of(void) + + if (!pdev) { + pr_err("Unable to find DSS platform device\n"); ++ of_node_put(node); + return -ENODEV; + } + + r = of_platform_populate(node, NULL, NULL, &pdev->dev); + put_device(&pdev->dev); ++ of_node_put(node); + if (r) { + pr_err("Unable to populate DSS submodule devices\n"); + return r; +diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c +index 765809b214e71..bf50acd6b8a3d 100644 +--- a/arch/arm/mach-omap2/pdata-quirks.c ++++ b/arch/arm/mach-omap2/pdata-quirks.c +@@ -587,6 +587,8 @@ pdata_quirks_init_clocks(const struct of_device_id *omap_dt_match_table) + + of_platform_populate(np, omap_dt_match_table, + omap_auxdata_lookup, NULL); ++ ++ of_node_put(np); + } + } + +diff --git a/arch/arm/mach-omap2/prm3xxx.c b/arch/arm/mach-omap2/prm3xxx.c +index 1b442b1285693..63e73e9b82bc6 100644 +--- a/arch/arm/mach-omap2/prm3xxx.c ++++ b/arch/arm/mach-omap2/prm3xxx.c +@@ -708,6 +708,7 @@ static int omap3xxx_prm_late_init(void) + } + + irq_num = of_irq_get(np, 0); ++ of_node_put(np); + if (irq_num == -EPROBE_DEFER) + return irq_num; + +diff --git a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c +index 09ef73b99dd86..ba44cec5e59ac 100644 +--- a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c ++++ b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c +@@ -125,6 +125,7 @@ remove: + + list_for_each_entry_safe(pos, tmp, &quirk_list, list) { + list_del(&pos->list); ++ of_node_put(pos->np); + kfree(pos); + } + +@@ -174,11 +175,12 @@ static int __init rcar_gen2_regulator_quirk(void) + memcpy(&quirk->i2c_msg, id->data, sizeof(quirk->i2c_msg)); + + quirk->id = id; +- quirk->np = np; ++ quirk->np = of_node_get(np); + quirk->i2c_msg.addr = addr; + + ret = of_irq_parse_one(np, 0, argsa); + if (ret) { /* Skip invalid entry and continue */ ++ of_node_put(np); + kfree(quirk); + continue; + } +@@ -225,6 +227,7 @@ err_free: + err_mem: + list_for_each_entry_safe(pos, tmp, &quirk_list, list) { + list_del(&pos->list); ++ of_node_put(pos->np); + kfree(pos); + } + +diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c +index e1ca6a5732d27..15e8a321a713b 100644 +--- a/arch/arm/mach-zynq/common.c ++++ b/arch/arm/mach-zynq/common.c +@@ -77,6 +77,7 @@ static int __init zynq_get_revision(void) + } + + zynq_devcfg_base = of_iomap(np, 0); ++ of_node_put(np); + if (!zynq_devcfg_base) { + pr_err("%s: Unable to map I/O memory\n", __func__); + return -1; +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index 8b6f090e0364c..69e7e293f72e4 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -220,6 +220,7 @@ config ARM64 + select THREAD_INFO_IN_TASK + select HAVE_ARCH_USERFAULTFD_MINOR if USERFAULTFD + select TRACE_IRQFLAGS_SUPPORT ++ select TRACE_IRQFLAGS_NMI_SUPPORT + help + ARM 64-bit (AArch64) Linux support. + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts +index 097a5511523ad..09eee653d5caa 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts +@@ -40,7 +40,7 @@ + leds { + compatible = "gpio-leds"; + +- status { ++ led-0 { + label = "orangepi:green:status"; + gpios = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */ + }; +diff --git a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +index 2f77dc40b9b82..6b99d903b4791 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -49,7 +49,7 @@ + wps { + label = "wps"; + linux,code = <KEY_WPS_BUTTON>; +- gpios = <&pio 102 GPIO_ACTIVE_HIGH>; ++ gpios = <&pio 102 GPIO_ACTIVE_LOW>; + }; + }; + +diff --git a/arch/arm64/boot/dts/mediatek/mt8192.dtsi b/arch/arm64/boot/dts/mediatek/mt8192.dtsi +index cb1e46d2c1ba6..d1e63527b3875 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8192.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8192.dtsi +@@ -39,7 +39,7 @@ + reg = <0x000>; + enable-method = "psci"; + clock-frequency = <1701000000>; +- cpu-idle-states = <&cpuoff_l &clusteroff_l>; ++ cpu-idle-states = <&cpu_sleep_l &cluster_sleep_l>; + next-level-cache = <&l2_0>; + capacity-dmips-mhz = <530>; + }; +@@ -50,7 +50,7 @@ + reg = <0x100>; + enable-method = "psci"; + clock-frequency = <1701000000>; +- cpu-idle-states = <&cpuoff_l &clusteroff_l>; ++ cpu-idle-states = <&cpu_sleep_l &cluster_sleep_l>; + next-level-cache = <&l2_0>; + capacity-dmips-mhz = <530>; + }; +@@ -61,7 +61,7 @@ + reg = <0x200>; + enable-method = "psci"; + clock-frequency = <1701000000>; +- cpu-idle-states = <&cpuoff_l &clusteroff_l>; ++ cpu-idle-states = <&cpu_sleep_l &cluster_sleep_l>; + next-level-cache = <&l2_0>; + capacity-dmips-mhz = <530>; + }; +@@ -72,7 +72,7 @@ + reg = <0x300>; + enable-method = "psci"; + clock-frequency = <1701000000>; +- cpu-idle-states = <&cpuoff_l &clusteroff_l>; ++ cpu-idle-states = <&cpu_sleep_l &cluster_sleep_l>; + next-level-cache = <&l2_0>; + capacity-dmips-mhz = <530>; + }; +@@ -83,7 +83,7 @@ + reg = <0x400>; + enable-method = "psci"; + clock-frequency = <2171000000>; +- cpu-idle-states = <&cpuoff_b &clusteroff_b>; ++ cpu-idle-states = <&cpu_sleep_b &cluster_sleep_b>; + next-level-cache = <&l2_1>; + capacity-dmips-mhz = <1024>; + }; +@@ -94,7 +94,7 @@ + reg = <0x500>; + enable-method = "psci"; + clock-frequency = <2171000000>; +- cpu-idle-states = <&cpuoff_b &clusteroff_b>; ++ cpu-idle-states = <&cpu_sleep_b &cluster_sleep_b>; + next-level-cache = <&l2_1>; + capacity-dmips-mhz = <1024>; + }; +@@ -105,7 +105,7 @@ + reg = <0x600>; + enable-method = "psci"; + clock-frequency = <2171000000>; +- cpu-idle-states = <&cpuoff_b &clusteroff_b>; ++ cpu-idle-states = <&cpu_sleep_b &cluster_sleep_b>; + next-level-cache = <&l2_1>; + capacity-dmips-mhz = <1024>; + }; +@@ -116,7 +116,7 @@ + reg = <0x700>; + enable-method = "psci"; + clock-frequency = <2171000000>; +- cpu-idle-states = <&cpuoff_b &clusteroff_b>; ++ cpu-idle-states = <&cpu_sleep_b &cluster_sleep_b>; + next-level-cache = <&l2_1>; + capacity-dmips-mhz = <1024>; + }; +@@ -168,8 +168,8 @@ + }; + + idle-states { +- entry-method = "arm,psci"; +- cpuoff_l: cpuoff_l { ++ entry-method = "psci"; ++ cpu_sleep_l: cpu-sleep-l { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x00010001>; + local-timer-stop; +@@ -177,7 +177,7 @@ + exit-latency-us = <140>; + min-residency-us = <780>; + }; +- cpuoff_b: cpuoff_b { ++ cpu_sleep_b: cpu-sleep-b { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x00010001>; + local-timer-stop; +@@ -185,7 +185,7 @@ + exit-latency-us = <145>; + min-residency-us = <720>; + }; +- clusteroff_l: clusteroff_l { ++ cluster_sleep_l: cluster-sleep-l { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x01010002>; + local-timer-stop; +@@ -193,7 +193,7 @@ + exit-latency-us = <155>; + min-residency-us = <860>; + }; +- clusteroff_b: clusteroff_b { ++ cluster_sleep_b: cluster-sleep-b { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x01010002>; + local-timer-stop; +diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi +index 062e87e893316..5b0bc9aa1a426 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi +@@ -1583,6 +1583,7 @@ + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x0 0x30000000 0x50000>; ++ no-memory-wc; + + cpu_bpmp_tx: sram@4e000 { + reg = <0x4e000 0x1000>; +@@ -1635,7 +1636,7 @@ + iommus = <&smmu TEGRA186_SID_BPMP>; + mboxes = <&hsp_top0 TEGRA_HSP_MBOX_TYPE_DB + TEGRA_HSP_DB_MASTER_BPMP>; +- shmem = <&cpu_bpmp_tx &cpu_bpmp_rx>; ++ shmem = <&cpu_bpmp_tx>, <&cpu_bpmp_rx>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; +diff --git a/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi b/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi +index c4058ee36fecb..1a444705517f3 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi +@@ -75,7 +75,7 @@ + + /* SDMMC1 (SD/MMC) */ + mmc@3400000 { +- cd-gpios = <&gpio TEGRA194_MAIN_GPIO(A, 0) GPIO_ACTIVE_LOW>; ++ cd-gpios = <&gpio TEGRA194_MAIN_GPIO(G, 7) GPIO_ACTIVE_LOW>; + }; + + /* SDMMC4 (eMMC) */ +diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi b/arch/arm64/boot/dts/nvidia/tegra194.dtsi +index 510d2974470cd..ca71b71d801a6 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi +@@ -2249,6 +2249,7 @@ + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x0 0x40000000 0x50000>; ++ no-memory-wc; + + cpu_bpmp_tx: sram@4e000 { + reg = <0x4e000 0x1000>; +@@ -2267,7 +2268,7 @@ + compatible = "nvidia,tegra186-bpmp"; + mboxes = <&hsp_top0 TEGRA_HSP_MBOX_TYPE_DB + TEGRA_HSP_DB_MASTER_BPMP>; +- shmem = <&cpu_bpmp_tx &cpu_bpmp_rx>; ++ shmem = <&cpu_bpmp_tx>, <&cpu_bpmp_rx>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; +diff --git a/arch/arm64/boot/dts/nvidia/tegra234.dtsi b/arch/arm64/boot/dts/nvidia/tegra234.dtsi +index f0efb3a628040..2b47845722206 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra234.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra234.dtsi +@@ -122,21 +122,22 @@ + }; + }; + +- sysram@40000000 { ++ sram@40000000 { + compatible = "nvidia,tegra234-sysram", "mmio-sram"; +- reg = <0x0 0x40000000 0x0 0x50000>; ++ reg = <0x0 0x40000000 0x0 0x80000>; + #address-cells = <1>; + #size-cells = <1>; +- ranges = <0x0 0x0 0x40000000 0x50000>; ++ ranges = <0x0 0x0 0x40000000 0x80000>; ++ no-memory-wc; + +- cpu_bpmp_tx: shmem@4e000 { +- reg = <0x4e000 0x1000>; ++ cpu_bpmp_tx: sram@70000 { ++ reg = <0x70000 0x1000>; + label = "cpu-bpmp-tx"; + pool; + }; + +- cpu_bpmp_rx: shmem@4f000 { +- reg = <0x4f000 0x1000>; ++ cpu_bpmp_rx: sram@71000 { ++ reg = <0x71000 0x1000>; + label = "cpu-bpmp-rx"; + pool; + }; +@@ -146,7 +147,7 @@ + compatible = "nvidia,tegra234-bpmp", "nvidia,tegra186-bpmp"; + mboxes = <&hsp_top0 TEGRA_HSP_MBOX_TYPE_DB + TEGRA_HSP_DB_MASTER_BPMP>; +- shmem = <&cpu_bpmp_tx &cpu_bpmp_rx>; ++ shmem = <&cpu_bpmp_tx>, <&cpu_bpmp_rx>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; +diff --git a/arch/arm64/boot/dts/qcom/ipq8074.dtsi b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +index fea415302408f..6b9ac05504905 100644 +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -437,7 +437,7 @@ + status = "disabled"; + }; + +- qpic_nand: nand@79b0000 { ++ qpic_nand: nand-controller@79b0000 { + compatible = "qcom,ipq8074-nand"; + reg = <0x079b0000 0x10000>; + #address-cells = <1>; +diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi +index 8b27242724641..19e201f52b167 100644 +--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi ++++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi +@@ -1747,8 +1747,8 @@ + <&rpmpd MSM8916_VDDMX>; + power-domain-names = "cx", "mx"; + +- qcom,state = <&wcnss_smp2p_out 0>; +- qcom,state-names = "stop"; ++ qcom,smem-states = <&wcnss_smp2p_out 0>; ++ qcom,smem-state-names = "stop"; + + pinctrl-names = "default"; + pinctrl-0 = <&wcnss_pin_a>; +diff --git a/arch/arm64/boot/dts/qcom/qcs404.dtsi b/arch/arm64/boot/dts/qcom/qcs404.dtsi +index ca5be16479809..18cc8e3bc93ac 100644 +--- a/arch/arm64/boot/dts/qcom/qcs404.dtsi ++++ b/arch/arm64/boot/dts/qcom/qcs404.dtsi +@@ -548,7 +548,7 @@ + compatible = "snps,dwc3"; + reg = <0x07580000 0xcd00>; + interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; +- phys = <&usb2_phy_sec>, <&usb3_phy>; ++ phys = <&usb2_phy_prim>, <&usb3_phy>; + phy-names = "usb2-phy", "usb3-phy"; + snps,has-lpm-erratum; + snps,hird-threshold = /bits/ 8 <0x10>; +@@ -577,7 +577,7 @@ + compatible = "snps,dwc3"; + reg = <0x078c0000 0xcc00>; + interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>; +- phys = <&usb2_phy_prim>; ++ phys = <&usb2_phy_sec>; + phy-names = "usb2-phy"; + snps,has-lpm-erratum; + snps,hird-threshold = /bits/ 8 <0x10>; +diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi +index 70c88c37de321..a9d36ac6cb90e 100644 +--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi ++++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi +@@ -42,6 +42,7 @@ + */ + + /delete-node/ &hyp_mem; ++/delete-node/ &ipa_fw_mem; + /delete-node/ &xbl_mem; + /delete-node/ &aop_mem; + /delete-node/ &sec_apps_mem; +diff --git a/arch/arm64/boot/dts/qcom/sdm630.dtsi b/arch/arm64/boot/dts/qcom/sdm630.dtsi +index a8724fd60645f..952bb133914f4 100644 +--- a/arch/arm64/boot/dts/qcom/sdm630.dtsi ++++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi +@@ -8,6 +8,7 @@ + #include <dt-bindings/clock/qcom,gpucc-sdm660.h> + #include <dt-bindings/clock/qcom,mmcc-sdm660.h> + #include <dt-bindings/clock/qcom,rpmcc.h> ++#include <dt-bindings/interconnect/qcom,sdm660.h> + #include <dt-bindings/power/qcom-rpmpd.h> + #include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> +@@ -1041,11 +1042,13 @@ + nvmem-cells = <&gpu_speed_bin>; + nvmem-cell-names = "speed_bin"; + +- interconnects = <&gnoc 1 &bimc 5>; ++ interconnects = <&bimc MASTER_OXILI &bimc SLAVE_EBI>; + interconnect-names = "gfx-mem"; + + operating-points-v2 = <&gpu_sdm630_opp_table>; + ++ status = "disabled"; ++ + gpu_sdm630_opp_table: opp-table { + compatible = "operating-points-v2"; + opp-775000000 { +@@ -1251,7 +1254,7 @@ + #phy-cells = <0>; + + clocks = <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, +- <&gcc GCC_RX1_USB2_CLKREF_CLK>; ++ <&gcc GCC_RX0_USB2_CLKREF_CLK>; + clock-names = "cfg_ahb", "ref"; + + resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>; +diff --git a/arch/arm64/boot/dts/qcom/sdm636-sony-xperia-ganges-mermaid.dts b/arch/arm64/boot/dts/qcom/sdm636-sony-xperia-ganges-mermaid.dts +index bba1c2bce2131..0afe9eee025e1 100644 +--- a/arch/arm64/boot/dts/qcom/sdm636-sony-xperia-ganges-mermaid.dts ++++ b/arch/arm64/boot/dts/qcom/sdm636-sony-xperia-ganges-mermaid.dts +@@ -18,7 +18,7 @@ + }; + + &sdc2_state_on { +- pinconf-clk { ++ clk { + drive-strength = <14>; + }; + }; +diff --git a/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts b/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts +index 58b6b2742d3f9..47f8e5397ebba 100644 +--- a/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts ++++ b/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts +@@ -88,11 +88,19 @@ + status = "okay"; + }; + +-&sdc2_state_off { ++&sdc2_off_state { + sd-cd { + pins = "gpio98"; ++ drive-strength = <2>; + bias-disable; ++ }; ++}; ++ ++&sdc2_on_state { ++ sd-cd { ++ pins = "gpio98"; + drive-strength = <2>; ++ bias-pull-up; + }; + }; + +@@ -102,32 +110,6 @@ + + &tlmm { + gpio-reserved-ranges = <22 2>, <28 6>; +- +- sdc2_state_on: sdc2-on { +- clk { +- pins = "sdc2_clk"; +- bias-disable; +- drive-strength = <16>; +- }; +- +- cmd { +- pins = "sdc2_cmd"; +- bias-pull-up; +- drive-strength = <10>; +- }; +- +- data { +- pins = "sdc2_data"; +- bias-pull-up; +- drive-strength = <10>; +- }; +- +- sd-cd { +- pins = "gpio98"; +- bias-pull-up; +- drive-strength = <2>; +- }; +- }; + }; + + &usb3 { +diff --git a/arch/arm64/boot/dts/qcom/sm6125.dtsi b/arch/arm64/boot/dts/qcom/sm6125.dtsi +index 9f476e3d0720b..f89af5e351127 100644 +--- a/arch/arm64/boot/dts/qcom/sm6125.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm6125.dtsi +@@ -336,23 +336,43 @@ + interrupt-controller; + #interrupt-cells = <2>; + +- sdc2_state_off: sdc2-off { ++ sdc2_off_state: sdc2-off-state { + clk { + pins = "sdc2_clk"; +- bias-disable; + drive-strength = <2>; ++ bias-disable; + }; + + cmd { + pins = "sdc2_cmd"; ++ drive-strength = <2>; + bias-pull-up; ++ }; ++ ++ data { ++ pins = "sdc2_data"; + drive-strength = <2>; ++ bias-pull-up; ++ }; ++ }; ++ ++ sdc2_on_state: sdc2-on-state { ++ clk { ++ pins = "sdc2_clk"; ++ drive-strength = <16>; ++ bias-disable; ++ }; ++ ++ cmd { ++ pins = "sdc2_cmd"; ++ drive-strength = <10>; ++ bias-pull-up; + }; + + data { + pins = "sdc2_data"; ++ drive-strength = <10>; + bias-pull-up; +- drive-strength = <2>; + }; + }; + }; +@@ -417,8 +437,8 @@ + <&xo_board>; + clock-names = "iface", "core", "xo"; + +- pinctrl-0 = <&sdc2_state_on>; +- pinctrl-1 = <&sdc2_state_off>; ++ pinctrl-0 = <&sdc2_on_state>; ++ pinctrl-1 = <&sdc2_off_state>; + pinctrl-names = "default", "sleep"; + + bus-width = <4>; +diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi +index 2786e2c8e5659..b710bca456489 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi +@@ -1472,6 +1472,8 @@ + clock-names = "pipe0"; + + #phy-cells = <0>; ++ ++ #clock-cells = <0>; + clock-output-names = "pcie_0_pipe_clk"; + }; + }; +@@ -1578,6 +1580,8 @@ + clock-names = "pipe0"; + + #phy-cells = <0>; ++ ++ #clock-cells = <0>; + clock-output-names = "pcie_1_pipe_clk"; + }; + }; +@@ -1684,6 +1688,8 @@ + clock-names = "pipe0"; + + #phy-cells = <0>; ++ ++ #clock-cells = <0>; + clock-output-names = "pcie_2_pipe_clk"; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi b/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi +index 2692cc64bff61..48e0c0494f6a0 100644 +--- a/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi ++++ b/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi +@@ -146,7 +146,7 @@ + }; + }; + +- reg_audio: regulator_audio { ++ reg_audio: regulator-audio { + compatible = "regulator-fixed"; + regulator-name = "audio-1.8V"; + regulator-min-microvolt = <1800000>; +@@ -174,7 +174,7 @@ + vin-supply = <®_lcd>; + }; + +- reg_cam0: regulator_camera { ++ reg_cam0: regulator-cam0 { + compatible = "regulator-fixed"; + regulator-name = "reg_cam0"; + regulator-min-microvolt = <1800000>; +@@ -183,7 +183,7 @@ + enable-active-high; + }; + +- reg_cam1: regulator_camera { ++ reg_cam1: regulator-cam1 { + compatible = "regulator-fixed"; + regulator-name = "reg_cam1"; + regulator-min-microvolt = <1800000>; +diff --git a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi +index d597772c4c37e..9eb08be3b98e2 100644 +--- a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi +@@ -1953,7 +1953,7 @@ + cpu-thermal { + polling-delay-passive = <250>; + polling-delay = <0>; +- thermal-sensors = <&thermal 0>; ++ thermal-sensors = <&thermal>; + sustainable-power = <717>; + + cooling-maps { +diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi +index 0ea300a8147d0..9e616b0f04d46 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi +@@ -2102,7 +2102,7 @@ + cpu-thermal { + polling-delay-passive = <250>; + polling-delay = <0>; +- thermal-sensors = <&thermal 0>; ++ thermal-sensors = <&thermal>; + sustainable-power = <717>; + + cooling-maps { +diff --git a/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi b/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi +index be97da1322580..ba75adedbf79b 100644 +--- a/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi ++++ b/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi +@@ -599,8 +599,8 @@ + compatible = "socionext,uniphier-dwc3", "snps,dwc3"; + status = "disabled"; + reg = <0x65a00000 0xcd00>; +- interrupt-names = "host", "peripheral"; +- interrupts = <0 134 4>, <0 135 4>; ++ interrupt-names = "dwc_usb3"; ++ interrupts = <0 134 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb0>, <&pinctrl_usb2>; + clock-names = "ref", "bus_early", "suspend"; +@@ -701,8 +701,8 @@ + compatible = "socionext,uniphier-dwc3", "snps,dwc3"; + status = "disabled"; + reg = <0x65c00000 0xcd00>; +- interrupt-names = "host", "peripheral"; +- interrupts = <0 137 4>, <0 138 4>; ++ interrupt-names = "dwc_usb3"; ++ interrupts = <0 137 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb1>, <&pinctrl_usb3>; + clock-names = "ref", "bus_early", "suspend"; +diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig +index 55f19450091b2..1a5406e599bab 100644 +--- a/arch/arm64/crypto/Kconfig ++++ b/arch/arm64/crypto/Kconfig +@@ -59,6 +59,7 @@ config CRYPTO_GHASH_ARM64_CE + select CRYPTO_HASH + select CRYPTO_GF128MUL + select CRYPTO_LIB_AES ++ select CRYPTO_AEAD + + config CRYPTO_CRCT10DIF_ARM64_CE + tristate "CRCT10DIF digest algorithm using PMULL instructions" +diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h +index 5e73d7f7d1e7c..d9bf3d12a2b85 100644 +--- a/arch/arm64/include/asm/processor.h ++++ b/arch/arm64/include/asm/processor.h +@@ -204,8 +204,9 @@ void tls_preserve_current_state(void); + + static inline void start_thread_common(struct pt_regs *regs, unsigned long pc) + { ++ s32 previous_syscall = regs->syscallno; + memset(regs, 0, sizeof(*regs)); +- forget_syscall(regs); ++ regs->syscallno = previous_syscall; + regs->pc = pc; + + if (system_uses_irq_prio_masking()) +diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c +index 0e86e8b9ceddf..c5da9d1e954a0 100644 +--- a/arch/arm64/kernel/armv8_deprecated.c ++++ b/arch/arm64/kernel/armv8_deprecated.c +@@ -59,6 +59,7 @@ struct insn_emulation { + static LIST_HEAD(insn_emulation); + static int nr_insn_emulated __initdata; + static DEFINE_RAW_SPINLOCK(insn_emulation_lock); ++static DEFINE_MUTEX(insn_emulation_mutex); + + static void register_emulation_hooks(struct insn_emulation_ops *ops) + { +@@ -207,10 +208,10 @@ static int emulation_proc_handler(struct ctl_table *table, int write, + loff_t *ppos) + { + int ret = 0; +- struct insn_emulation *insn = (struct insn_emulation *) table->data; ++ struct insn_emulation *insn = container_of(table->data, struct insn_emulation, current_mode); + enum insn_emulation_mode prev_mode = insn->current_mode; + +- table->data = &insn->current_mode; ++ mutex_lock(&insn_emulation_mutex); + ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); + + if (ret || !write || prev_mode == insn->current_mode) +@@ -223,7 +224,7 @@ static int emulation_proc_handler(struct ctl_table *table, int write, + update_insn_emulation_mode(insn, INSN_UNDEF); + } + ret: +- table->data = insn; ++ mutex_unlock(&insn_emulation_mutex); + return ret; + } + +@@ -247,7 +248,7 @@ static void __init register_insn_emulation_sysctl(void) + sysctl->maxlen = sizeof(int); + + sysctl->procname = insn->ops->name; +- sysctl->data = insn; ++ sysctl->data = &insn->current_mode; + sysctl->extra1 = &insn->min; + sysctl->extra2 = &insn->max; + sysctl->proc_handler = emulation_proc_handler; +diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c +index e71c9cfb46e8c..474aa55c2f680 100644 +--- a/arch/arm64/kernel/cpufeature.c ++++ b/arch/arm64/kernel/cpufeature.c +@@ -536,7 +536,7 @@ static const struct arm64_ftr_bits ftr_id_pfr2[] = { + + static const struct arm64_ftr_bits ftr_id_dfr0[] = { + /* [31:28] TraceFilt */ +- S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_PERFMON_SHIFT, 4, 0xf), ++ S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_DFR0_PERFMON_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_MPROFDBG_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_MMAPTRC_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_COPTRC_SHIFT, 4, 0), +diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c +index 46a0b4d6e2519..db93ce2b0113b 100644 +--- a/arch/arm64/kernel/hibernate.c ++++ b/arch/arm64/kernel/hibernate.c +@@ -326,11 +326,6 @@ static void swsusp_mte_restore_tags(void) + unsigned long pfn = xa_state.xa_index; + struct page *page = pfn_to_online_page(pfn); + +- /* +- * It is not required to invoke page_kasan_tag_reset(page) +- * at this point since the tags stored in page->flags are +- * already restored. +- */ + mte_restore_page_tags(page_address(page), tags); + + mte_free_tag_storage(tags); +diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c +index 7c1c82c8115cc..10207e3e5ae20 100644 +--- a/arch/arm64/kernel/mte.c ++++ b/arch/arm64/kernel/mte.c +@@ -44,15 +44,6 @@ static void mte_sync_page_tags(struct page *page, pte_t old_pte, + if (!pte_is_tagged) + return; + +- page_kasan_tag_reset(page); +- /* +- * We need smp_wmb() in between setting the flags and clearing the +- * tags because if another thread reads page->flags and builds a +- * tagged address out of it, there is an actual dependency to the +- * memory access, but on the current thread we do not guarantee that +- * the new page->flags are visible before the tags were updated. +- */ +- smp_wmb(); + mte_clear_page_tags(page_address(page)); + } + +diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c +index a34b01cc8ab9e..4db5409f40c4f 100644 +--- a/arch/arm64/kvm/hyp/nvhe/switch.c ++++ b/arch/arm64/kvm/hyp/nvhe/switch.c +@@ -279,5 +279,5 @@ void __noreturn hyp_panic(void) + + asmlinkage void kvm_unexpected_el2_exception(void) + { +- return __kvm_unexpected_el2_exception(); ++ __kvm_unexpected_el2_exception(); + } +diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c +index d88d3c143a735..813e6e2178c16 100644 +--- a/arch/arm64/kvm/hyp/vhe/switch.c ++++ b/arch/arm64/kvm/hyp/vhe/switch.c +@@ -220,5 +220,5 @@ void __noreturn hyp_panic(void) + + asmlinkage void kvm_unexpected_el2_exception(void) + { +- return __kvm_unexpected_el2_exception(); ++ __kvm_unexpected_el2_exception(); + } +diff --git a/arch/arm64/mm/copypage.c b/arch/arm64/mm/copypage.c +index 0dea80bf6de46..24913271e898c 100644 +--- a/arch/arm64/mm/copypage.c ++++ b/arch/arm64/mm/copypage.c +@@ -23,15 +23,6 @@ void copy_highpage(struct page *to, struct page *from) + + if (system_supports_mte() && test_bit(PG_mte_tagged, &from->flags)) { + set_bit(PG_mte_tagged, &to->flags); +- page_kasan_tag_reset(to); +- /* +- * We need smp_wmb() in between setting the flags and clearing the +- * tags because if another thread reads page->flags and builds a +- * tagged address out of it, there is an actual dependency to the +- * memory access, but on the current thread we do not guarantee that +- * the new page->flags are visible before the tags were updated. +- */ +- smp_wmb(); + mte_copy_page_tags(kto, kfrom); + } + } +diff --git a/arch/arm64/mm/mteswap.c b/arch/arm64/mm/mteswap.c +index 7c4ef56265ee1..c52c1847079c1 100644 +--- a/arch/arm64/mm/mteswap.c ++++ b/arch/arm64/mm/mteswap.c +@@ -53,15 +53,6 @@ bool mte_restore_tags(swp_entry_t entry, struct page *page) + if (!tags) + return false; + +- page_kasan_tag_reset(page); +- /* +- * We need smp_wmb() in between setting the flags and clearing the +- * tags because if another thread reads page->flags and builds a +- * tagged address out of it, there is an actual dependency to the +- * memory access, but on the current thread we do not guarantee that +- * the new page->flags are visible before the tags were updated. +- */ +- smp_wmb(); + mte_restore_page_tags(page_address(page), tags); + + return true; +diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h +index 2d8bcdc27d7f8..05e7c9ad1a965 100644 +--- a/arch/ia64/include/asm/processor.h ++++ b/arch/ia64/include/asm/processor.h +@@ -542,7 +542,7 @@ ia64_get_irr(unsigned int vector) + { + unsigned int reg = vector / 64; + unsigned int bit = vector % 64; +- u64 irr; ++ unsigned long irr; + + switch (reg) { + case 0: irr = ia64_getreg(_IA64_REG_CR_IRR0); break; +diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c +index 4184d641f05e0..33a02f3814f58 100644 +--- a/arch/mips/kernel/proc.c ++++ b/arch/mips/kernel/proc.c +@@ -172,7 +172,7 @@ static void *c_start(struct seq_file *m, loff_t *pos) + { + unsigned long i = *pos; + +- return i < NR_CPUS ? (void *) (i + 1) : NULL; ++ return i < nr_cpu_ids ? (void *) (i + 1) : NULL; + } + + static void *c_next(struct seq_file *m, void *v, loff_t *pos) +diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c +index 3d0cf471f2fe1..b2cc2c2dd4bfc 100644 +--- a/arch/mips/kernel/vdso.c ++++ b/arch/mips/kernel/vdso.c +@@ -159,7 +159,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) + /* Map GIC user page. */ + if (gic_size) { + gic_base = (unsigned long)mips_gic_base + MIPS_GIC_USER_OFS; +- gic_pfn = virt_to_phys((void *)gic_base) >> PAGE_SHIFT; ++ gic_pfn = PFN_DOWN(__pa(gic_base)); + + ret = io_remap_pfn_range(vma, base, gic_pfn, gic_size, + pgprot_noncached(vma->vm_page_prot)); +diff --git a/arch/mips/mm/physaddr.c b/arch/mips/mm/physaddr.c +index a1ced5e449511..f9b8c85e98433 100644 +--- a/arch/mips/mm/physaddr.c ++++ b/arch/mips/mm/physaddr.c +@@ -5,6 +5,7 @@ + #include <linux/mmdebug.h> + #include <linux/mm.h> + ++#include <asm/addrspace.h> + #include <asm/sections.h> + #include <asm/io.h> + #include <asm/page.h> +@@ -12,15 +13,6 @@ + + static inline bool __debug_virt_addr_valid(unsigned long x) + { +- /* high_memory does not get immediately defined, and there +- * are early callers of __pa() against PAGE_OFFSET +- */ +- if (!high_memory && x >= PAGE_OFFSET) +- return true; +- +- if (high_memory && x >= PAGE_OFFSET && x < (unsigned long)high_memory) +- return true; +- + /* + * MAX_DMA_ADDRESS is a virtual address that may not correspond to an + * actual physical address. Enough code relies on +@@ -30,7 +22,9 @@ static inline bool __debug_virt_addr_valid(unsigned long x) + if (x == MAX_DMA_ADDRESS) + return true; + +- return false; ++ return x >= PAGE_OFFSET && (KSEGX(x) < KSEG2 || ++ IS_ENABLED(CONFIG_EVA) || ++ !IS_ENABLED(CONFIG_HIGHMEM)); + } + + phys_addr_t __virt_to_phys(volatile const void *x) +diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c +index 4ed4942d8312b..394e6e14e5c42 100644 +--- a/arch/parisc/kernel/cache.c ++++ b/arch/parisc/kernel/cache.c +@@ -46,9 +46,6 @@ void flush_icache_page_asm(unsigned long phys_addr, unsigned long vaddr); + */ + DEFINE_SPINLOCK(pa_tlb_flush_lock); + +-/* Swapper page setup lock. */ +-DEFINE_SPINLOCK(pa_swapper_pg_lock); +- + #if defined(CONFIG_64BIT) && defined(CONFIG_SMP) + int pa_serialize_tlb_flushes __ro_after_init; + #endif +diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c +index 776d624a7207b..d126e78e101ae 100644 +--- a/arch/parisc/kernel/drivers.c ++++ b/arch/parisc/kernel/drivers.c +@@ -520,7 +520,6 @@ alloc_pa_dev(unsigned long hpa, struct hardware_path *mod_path) + dev->id.hversion_rev = iodc_data[1] & 0x0f; + dev->id.sversion = ((iodc_data[4] & 0x0f) << 16) | + (iodc_data[5] << 8) | iodc_data[6]; +- dev->hpa.name = parisc_pathname(dev); + dev->hpa.start = hpa; + /* This is awkward. The STI spec says that gfx devices may occupy + * 32MB or 64MB. Unfortunately, we don't know how to tell whether +@@ -534,10 +533,10 @@ alloc_pa_dev(unsigned long hpa, struct hardware_path *mod_path) + dev->hpa.end = hpa + 0xfff; + } + dev->hpa.flags = IORESOURCE_MEM; +- name = parisc_hardware_description(&dev->id); +- if (name) { +- strlcpy(dev->name, name, sizeof(dev->name)); +- } ++ dev->hpa.name = dev->name; ++ name = parisc_hardware_description(&dev->id) ? : "unknown"; ++ snprintf(dev->name, sizeof(dev->name), "%s [%s]", ++ name, parisc_pathname(dev)); + + /* Silently fail things like mouse ports which are subsumed within + * the keyboard controller +diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl +index bf751e0732b70..c23f4fa170051 100644 +--- a/arch/parisc/kernel/syscalls/syscall.tbl ++++ b/arch/parisc/kernel/syscalls/syscall.tbl +@@ -413,7 +413,7 @@ + 412 32 utimensat_time64 sys_utimensat sys_utimensat + 413 32 pselect6_time64 sys_pselect6 compat_sys_pselect6_time64 + 414 32 ppoll_time64 sys_ppoll compat_sys_ppoll_time64 +-416 32 io_pgetevents_time64 sys_io_pgetevents sys_io_pgetevents ++416 32 io_pgetevents_time64 sys_io_pgetevents compat_sys_io_pgetevents_time64 + 417 32 recvmmsg_time64 sys_recvmmsg compat_sys_recvmmsg_time64 + 418 32 mq_timedsend_time64 sys_mq_timedsend sys_mq_timedsend + 419 32 mq_timedreceive_time64 sys_mq_timedreceive sys_mq_timedreceive +diff --git a/arch/powerpc/include/asm/archrandom.h b/arch/powerpc/include/asm/archrandom.h +index 9a53e29680f41..258174304904b 100644 +--- a/arch/powerpc/include/asm/archrandom.h ++++ b/arch/powerpc/include/asm/archrandom.h +@@ -38,12 +38,7 @@ static inline bool __must_check arch_get_random_seed_int(unsigned int *v) + #endif /* CONFIG_ARCH_RANDOM */ + + #ifdef CONFIG_PPC_POWERNV +-int powernv_hwrng_present(void); + int powernv_get_random_long(unsigned long *v); +-int powernv_get_random_real_mode(unsigned long *v); +-#else +-static inline int powernv_hwrng_present(void) { return 0; } +-static inline int powernv_get_random_real_mode(unsigned long *v) { return 0; } + #endif + + #endif /* _ASM_POWERPC_ARCHRANDOM_H */ +diff --git a/arch/powerpc/include/asm/simple_spinlock.h b/arch/powerpc/include/asm/simple_spinlock.h +index 8985791a2ba57..3c037a12c84db 100644 +--- a/arch/powerpc/include/asm/simple_spinlock.h ++++ b/arch/powerpc/include/asm/simple_spinlock.h +@@ -48,10 +48,11 @@ static inline int arch_spin_is_locked(arch_spinlock_t *lock) + static inline unsigned long __arch_spin_trylock(arch_spinlock_t *lock) + { + unsigned long tmp, token; ++ unsigned int eh = IS_ENABLED(CONFIG_PPC64); + + token = LOCK_TOKEN; + __asm__ __volatile__( +-"1: lwarx %0,0,%2,1\n\ ++"1: lwarx %0,0,%2,%[eh]\n\ + cmpwi 0,%0,0\n\ + bne- 2f\n\ + stwcx. %1,0,%2\n\ +@@ -59,7 +60,7 @@ static inline unsigned long __arch_spin_trylock(arch_spinlock_t *lock) + PPC_ACQUIRE_BARRIER + "2:" + : "=&r" (tmp) +- : "r" (token), "r" (&lock->slock) ++ : "r" (token), "r" (&lock->slock), [eh] "n" (eh) + : "cr0", "memory"); + + return tmp; +@@ -177,9 +178,10 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock) + static inline long __arch_read_trylock(arch_rwlock_t *rw) + { + long tmp; ++ unsigned int eh = IS_ENABLED(CONFIG_PPC64); + + __asm__ __volatile__( +-"1: lwarx %0,0,%1,1\n" ++"1: lwarx %0,0,%1,%[eh]\n" + __DO_SIGN_EXTEND + " addic. %0,%0,1\n\ + ble- 2f\n" +@@ -187,7 +189,7 @@ static inline long __arch_read_trylock(arch_rwlock_t *rw) + bne- 1b\n" + PPC_ACQUIRE_BARRIER + "2:" : "=&r" (tmp) +- : "r" (&rw->lock) ++ : "r" (&rw->lock), [eh] "n" (eh) + : "cr0", "xer", "memory"); + + return tmp; +@@ -200,17 +202,18 @@ static inline long __arch_read_trylock(arch_rwlock_t *rw) + static inline long __arch_write_trylock(arch_rwlock_t *rw) + { + long tmp, token; ++ unsigned int eh = IS_ENABLED(CONFIG_PPC64); + + token = WRLOCK_TOKEN; + __asm__ __volatile__( +-"1: lwarx %0,0,%2,1\n\ ++"1: lwarx %0,0,%2,%[eh]\n\ + cmpwi 0,%0,0\n\ + bne- 2f\n" + " stwcx. %1,0,%2\n\ + bne- 1b\n" + PPC_ACQUIRE_BARRIER + "2:" : "=&r" (tmp) +- : "r" (token), "r" (&rw->lock) ++ : "r" (token), "r" (&rw->lock), [eh] "n" (eh) + : "cr0", "memory"); + + return tmp; +diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile +index b1b23b4d56ba2..ed91d5b9ffc63 100644 +--- a/arch/powerpc/kernel/Makefile ++++ b/arch/powerpc/kernel/Makefile +@@ -20,6 +20,7 @@ CFLAGS_prom.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) + CFLAGS_prom_init.o += -fno-stack-protector + CFLAGS_prom_init.o += -DDISABLE_BRANCH_PROFILING + CFLAGS_prom_init.o += -ffreestanding ++CFLAGS_prom_init.o += $(call cc-option, -ftrivial-auto-var-init=uninitialized) + + ifdef CONFIG_FUNCTION_TRACER + # Do not trace early boot code +diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c +index 07093b7cdcb9a..a67fd54ccc573 100644 +--- a/arch/powerpc/kernel/iommu.c ++++ b/arch/powerpc/kernel/iommu.c +@@ -776,6 +776,11 @@ bool iommu_table_in_use(struct iommu_table *tbl) + /* ignore reserved bit0 */ + if (tbl->it_offset == 0) + start = 1; ++ ++ /* Simple case with no reserved MMIO32 region */ ++ if (!tbl->it_reserved_start && !tbl->it_reserved_end) ++ return find_next_bit(tbl->it_map, tbl->it_size, start) != tbl->it_size; ++ + end = tbl->it_reserved_start - tbl->it_offset; + if (find_next_bit(tbl->it_map, end, start) != end) + return true; +diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c +index c3573430919d2..fc5187c6559a1 100644 +--- a/arch/powerpc/kernel/pci-common.c ++++ b/arch/powerpc/kernel/pci-common.c +@@ -74,16 +74,32 @@ void set_pci_dma_ops(const struct dma_map_ops *dma_ops) + static int get_phb_number(struct device_node *dn) + { + int ret, phb_id = -1; +- u32 prop_32; + u64 prop; + + /* + * Try fixed PHB numbering first, by checking archs and reading +- * the respective device-tree properties. Firstly, try powernv by +- * reading "ibm,opal-phbid", only present in OPAL environment. ++ * the respective device-tree properties. Firstly, try reading ++ * standard "linux,pci-domain", then try reading "ibm,opal-phbid" ++ * (only present in powernv OPAL environment), then try device-tree ++ * alias and as the last try to use lower bits of "reg" property. + */ +- ret = of_property_read_u64(dn, "ibm,opal-phbid", &prop); ++ ret = of_get_pci_domain_nr(dn); ++ if (ret >= 0) { ++ prop = ret; ++ ret = 0; ++ } ++ if (ret) ++ ret = of_property_read_u64(dn, "ibm,opal-phbid", &prop); ++ + if (ret) { ++ ret = of_alias_get_id(dn, "pci"); ++ if (ret >= 0) { ++ prop = ret; ++ ret = 0; ++ } ++ } ++ if (ret) { ++ u32 prop_32; + ret = of_property_read_u32_index(dn, "reg", 1, &prop_32); + prop = prop_32; + } +@@ -95,10 +111,7 @@ static int get_phb_number(struct device_node *dn) + if ((phb_id >= 0) && !test_and_set_bit(phb_id, phb_bitmap)) + return phb_id; + +- /* +- * If not pseries nor powernv, or if fixed PHB numbering tried to add +- * the same PHB number twice, then fallback to dynamic PHB numbering. +- */ ++ /* If everything fails then fallback to dynamic PHB numbering. */ + phb_id = find_first_zero_bit(phb_bitmap, MAX_PHBS); + BUG_ON(phb_id >= MAX_PHBS); + set_bit(phb_id, phb_bitmap); +diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c +index 70b7a8f971538..b148629b7f033 100644 +--- a/arch/powerpc/kvm/book3s_hv_builtin.c ++++ b/arch/powerpc/kvm/book3s_hv_builtin.c +@@ -20,7 +20,7 @@ + #include <asm/interrupt.h> + #include <asm/kvm_ppc.h> + #include <asm/kvm_book3s.h> +-#include <asm/archrandom.h> ++#include <asm/machdep.h> + #include <asm/xics.h> + #include <asm/xive.h> + #include <asm/dbell.h> +@@ -177,13 +177,14 @@ EXPORT_SYMBOL_GPL(kvmppc_hcall_impl_hv_realmode); + + int kvmppc_hwrng_present(void) + { +- return powernv_hwrng_present(); ++ return ppc_md.get_random_seed != NULL; + } + EXPORT_SYMBOL_GPL(kvmppc_hwrng_present); + + long kvmppc_rm_h_random(struct kvm_vcpu *vcpu) + { +- if (powernv_get_random_real_mode(&vcpu->arch.regs.gpr[4])) ++ if (ppc_md.get_random_seed && ++ ppc_md.get_random_seed(&vcpu->arch.regs.gpr[4])) + return H_SUCCESS; + + return H_HARDWARE; +diff --git a/arch/powerpc/mm/nohash/8xx.c b/arch/powerpc/mm/nohash/8xx.c +index 0df9fe29dd567..5348e1f9eb940 100644 +--- a/arch/powerpc/mm/nohash/8xx.c ++++ b/arch/powerpc/mm/nohash/8xx.c +@@ -183,8 +183,8 @@ void mmu_mark_initmem_nx(void) + unsigned long boundary = strict_kernel_rwx_enabled() ? sinittext : etext8; + unsigned long einittext8 = ALIGN(__pa(_einittext), SZ_8M); + +- mmu_mapin_ram_chunk(0, boundary, PAGE_KERNEL_TEXT, false); +- mmu_mapin_ram_chunk(boundary, einittext8, PAGE_KERNEL, false); ++ if (!debug_pagealloc_enabled_or_kfence()) ++ mmu_mapin_ram_chunk(boundary, einittext8, PAGE_KERNEL, false); + + mmu_pin_tlb(block_mapped_ram, false); + } +diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c +index f288597714407..502e3d3d1dbf7 100644 +--- a/arch/powerpc/mm/pgtable_32.c ++++ b/arch/powerpc/mm/pgtable_32.c +@@ -138,9 +138,9 @@ void mark_initmem_nx(void) + unsigned long numpages = PFN_UP((unsigned long)_einittext) - + PFN_DOWN((unsigned long)_sinittext); + +- if (v_block_mapped((unsigned long)_sinittext)) { +- mmu_mark_initmem_nx(); +- } else { ++ mmu_mark_initmem_nx(); ++ ++ if (!v_block_mapped((unsigned long)_sinittext)) { + set_memory_nx((unsigned long)_sinittext, numpages); + set_memory_rw((unsigned long)_sinittext, numpages); + } +diff --git a/arch/powerpc/mm/ptdump/shared.c b/arch/powerpc/mm/ptdump/shared.c +index 03607ab90c66f..f884760ca5cfe 100644 +--- a/arch/powerpc/mm/ptdump/shared.c ++++ b/arch/powerpc/mm/ptdump/shared.c +@@ -17,9 +17,9 @@ static const struct flag_info flag_array[] = { + .clear = " ", + }, { + .mask = _PAGE_RW, +- .val = _PAGE_RW, +- .set = "rw", +- .clear = "r ", ++ .val = 0, ++ .set = "r ", ++ .clear = "rw", + }, { + .mask = _PAGE_EXEC, + .val = _PAGE_EXEC, +diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c +index e78de70509472..1078784b74c9b 100644 +--- a/arch/powerpc/perf/core-book3s.c ++++ b/arch/powerpc/perf/core-book3s.c +@@ -1320,27 +1320,22 @@ static void power_pmu_disable(struct pmu *pmu) + * a PMI happens during interrupt replay and perf counter + * values are cleared by PMU callbacks before replay. + * +- * If any PMC corresponding to the active PMU events are +- * overflown, disable the interrupt by clearing the paca +- * bit for PMI since we are disabling the PMU now. +- * Otherwise provide a warning if there is PMI pending, but +- * no counter is found overflown. ++ * Disable the interrupt by clearing the paca bit for PMI ++ * since we are disabling the PMU now. Otherwise provide a ++ * warning if there is PMI pending, but no counter is found ++ * overflown. ++ * ++ * Since power_pmu_disable runs under local_irq_save, it ++ * could happen that code hits a PMC overflow without PMI ++ * pending in paca. Hence only clear PMI pending if it was ++ * set. ++ * ++ * If a PMI is pending, then MSR[EE] must be disabled (because ++ * the masked PMI handler disabling EE). So it is safe to ++ * call clear_pmi_irq_pending(). + */ +- if (any_pmc_overflown(cpuhw)) { +- /* +- * Since power_pmu_disable runs under local_irq_save, it +- * could happen that code hits a PMC overflow without PMI +- * pending in paca. Hence only clear PMI pending if it was +- * set. +- * +- * If a PMI is pending, then MSR[EE] must be disabled (because +- * the masked PMI handler disabling EE). So it is safe to +- * call clear_pmi_irq_pending(). +- */ +- if (pmi_irq_pending()) +- clear_pmi_irq_pending(); +- } else +- WARN_ON(pmi_irq_pending()); ++ if (pmi_irq_pending()) ++ clear_pmi_irq_pending(); + + val = mmcra = cpuhw->mmcr.mmcra; + +diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype +index 87a95cbff2f3f..81f8c96348321 100644 +--- a/arch/powerpc/platforms/Kconfig.cputype ++++ b/arch/powerpc/platforms/Kconfig.cputype +@@ -170,11 +170,11 @@ config POWER9_CPU + + config E5500_CPU + bool "Freescale e5500" +- depends on E500 ++ depends on PPC64 && E500 + + config E6500_CPU + bool "Freescale e6500" +- depends on E500 ++ depends on PPC64 && E500 + + config 860_CPU + bool "8xx family" +diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c +index 82335e364c440..f630693c8de72 100644 +--- a/arch/powerpc/platforms/cell/axon_msi.c ++++ b/arch/powerpc/platforms/cell/axon_msi.c +@@ -226,6 +226,7 @@ static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg) + if (!prop) { + dev_dbg(&dev->dev, + "axon_msi: no msi-address-(32|64) properties found\n"); ++ of_node_put(dn); + return -ENOENT; + } + +diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c +index bed05b644c2c5..ed37a93bf858a 100644 +--- a/arch/powerpc/platforms/cell/spufs/inode.c ++++ b/arch/powerpc/platforms/cell/spufs/inode.c +@@ -659,6 +659,7 @@ spufs_init_isolated_loader(void) + return; + + loader = of_get_property(dn, "loader", &size); ++ of_node_put(dn); + if (!loader) + return; + +diff --git a/arch/powerpc/platforms/powernv/rng.c b/arch/powerpc/platforms/powernv/rng.c +index 236bd2ba51b98..5f81ff9b5265f 100644 +--- a/arch/powerpc/platforms/powernv/rng.c ++++ b/arch/powerpc/platforms/powernv/rng.c +@@ -29,15 +29,6 @@ struct powernv_rng { + + static DEFINE_PER_CPU(struct powernv_rng *, powernv_rng); + +-int powernv_hwrng_present(void) +-{ +- struct powernv_rng *rng; +- +- rng = get_cpu_var(powernv_rng); +- put_cpu_var(rng); +- return rng != NULL; +-} +- + static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val) + { + unsigned long parity; +@@ -58,17 +49,6 @@ static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val) + return val; + } + +-int powernv_get_random_real_mode(unsigned long *v) +-{ +- struct powernv_rng *rng; +- +- rng = raw_cpu_read(powernv_rng); +- +- *v = rng_whiten(rng, __raw_rm_readq(rng->regs_real)); +- +- return 1; +-} +- + static int powernv_get_random_darn(unsigned long *v) + { + unsigned long val; +@@ -105,12 +85,14 @@ int powernv_get_random_long(unsigned long *v) + { + struct powernv_rng *rng; + +- rng = get_cpu_var(powernv_rng); +- +- *v = rng_whiten(rng, in_be64(rng->regs)); +- +- put_cpu_var(rng); +- ++ if (mfmsr() & MSR_DR) { ++ rng = get_cpu_var(powernv_rng); ++ *v = rng_whiten(rng, in_be64(rng->regs)); ++ put_cpu_var(rng); ++ } else { ++ rng = raw_cpu_read(powernv_rng); ++ *v = rng_whiten(rng, __raw_rm_readq(rng->regs_real)); ++ } + return 1; + } + EXPORT_SYMBOL_GPL(powernv_get_random_long); +diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c +index b8f76f3fd9941..a14a88e5025e5 100644 +--- a/arch/powerpc/sysdev/fsl_pci.c ++++ b/arch/powerpc/sysdev/fsl_pci.c +@@ -520,6 +520,7 @@ int fsl_add_bridge(struct platform_device *pdev, int is_primary) + struct resource rsrc; + const int *bus_range; + u8 hdr_type, progif; ++ u32 class_code; + struct device_node *dev; + struct ccsr_pci __iomem *pci; + u16 temp; +@@ -593,6 +594,13 @@ int fsl_add_bridge(struct platform_device *pdev, int is_primary) + PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS; + if (fsl_pcie_check_link(hose)) + hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK; ++ /* Fix Class Code to PCI_CLASS_BRIDGE_PCI_NORMAL for pre-3.0 controller */ ++ if (in_be32(&pci->block_rev1) < PCIE_IP_REV_3_0) { ++ early_read_config_dword(hose, 0, 0, PCIE_FSL_CSR_CLASSCODE, &class_code); ++ class_code &= 0xff; ++ class_code |= PCI_CLASS_BRIDGE_PCI_NORMAL << 8; ++ early_write_config_dword(hose, 0, 0, PCIE_FSL_CSR_CLASSCODE, class_code); ++ } + } else { + /* + * Set PBFR(PCI Bus Function Register)[10] = 1 to +diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h +index 1d7a412056959..5ffaa60f1fa09 100644 +--- a/arch/powerpc/sysdev/fsl_pci.h ++++ b/arch/powerpc/sysdev/fsl_pci.h +@@ -18,6 +18,7 @@ struct platform_device; + + #define PCIE_LTSSM 0x0404 /* PCIE Link Training and Status */ + #define PCIE_LTSSM_L0 0x16 /* L0 state */ ++#define PCIE_FSL_CSR_CLASSCODE 0x474 /* FSL GPEX CSR */ + #define PCIE_IP_REV_2_2 0x02080202 /* PCIE IP block version Rev2.2 */ + #define PCIE_IP_REV_3_0 0x02080300 /* PCIE IP block version Rev3.0 */ + #define PIWAR_EN 0x80000000 /* Enable */ +diff --git a/arch/powerpc/sysdev/xive/spapr.c b/arch/powerpc/sysdev/xive/spapr.c +index 583b2c6df3909..2bf78a30238b9 100644 +--- a/arch/powerpc/sysdev/xive/spapr.c ++++ b/arch/powerpc/sysdev/xive/spapr.c +@@ -716,6 +716,7 @@ static bool xive_get_max_prio(u8 *max_prio) + } + + reg = of_get_property(rootdn, "ibm,plat-res-int-priorities", &len); ++ of_node_put(rootdn); + if (!reg) { + pr_err("Failed to read 'ibm,plat-res-int-priorities' property\n"); + return false; +diff --git a/arch/riscv/kernel/crash_save_regs.S b/arch/riscv/kernel/crash_save_regs.S +index 7832fb763abac..b2a1908c0463e 100644 +--- a/arch/riscv/kernel/crash_save_regs.S ++++ b/arch/riscv/kernel/crash_save_regs.S +@@ -44,7 +44,7 @@ SYM_CODE_START(riscv_crash_save_regs) + REG_S t6, PT_T6(a0) /* x31 */ + + csrr t1, CSR_STATUS +- csrr t2, CSR_EPC ++ auipc t2, 0x0 + csrr t3, CSR_TVAL + csrr t4, CSR_CAUSE + +diff --git a/arch/riscv/kernel/machine_kexec.c b/arch/riscv/kernel/machine_kexec.c +index df8e24559035c..ee79e6839b863 100644 +--- a/arch/riscv/kernel/machine_kexec.c ++++ b/arch/riscv/kernel/machine_kexec.c +@@ -138,19 +138,37 @@ void machine_shutdown(void) + #endif + } + ++/* Override the weak function in kernel/panic.c */ ++void crash_smp_send_stop(void) ++{ ++ static int cpus_stopped; ++ ++ /* ++ * This function can be called twice in panic path, but obviously ++ * we execute this only once. ++ */ ++ if (cpus_stopped) ++ return; ++ ++ smp_send_stop(); ++ cpus_stopped = 1; ++} ++ + /* + * machine_crash_shutdown - Prepare to kexec after a kernel crash + * + * This function is called by crash_kexec just before machine_kexec +- * below and its goal is similar to machine_shutdown, but in case of +- * a kernel crash. Since we don't handle such cases yet, this function +- * is empty. ++ * and its goal is to shutdown non-crashing cpus and save registers. + */ + void + machine_crash_shutdown(struct pt_regs *regs) + { ++ local_irq_disable(); ++ ++ /* shutdown non-crashing cpus */ ++ crash_smp_send_stop(); ++ + crash_save_cpu(regs, smp_processor_id()); +- machine_shutdown(); + pr_info("Starting crashdump kernel...\n"); + } + +@@ -171,7 +189,7 @@ machine_kexec(struct kimage *image) + struct kimage_arch *internal = &image->arch; + unsigned long jump_addr = (unsigned long) image->start; + unsigned long first_ind_entry = (unsigned long) &image->head; +- unsigned long this_cpu_id = smp_processor_id(); ++ unsigned long this_cpu_id = __smp_processor_id(); + unsigned long this_hart_id = cpuid_to_hartid_map(this_cpu_id); + unsigned long fdt_addr = internal->fdt_addr; + void *control_code_buffer = page_address(image->control_code_page); +diff --git a/arch/riscv/kernel/probes/uprobes.c b/arch/riscv/kernel/probes/uprobes.c +index 7a057b5f0adc7..c976a21cd4bd5 100644 +--- a/arch/riscv/kernel/probes/uprobes.c ++++ b/arch/riscv/kernel/probes/uprobes.c +@@ -59,8 +59,6 @@ int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) + + instruction_pointer_set(regs, utask->xol_vaddr); + +- regs->status &= ~SR_SPIE; +- + return 0; + } + +@@ -72,8 +70,6 @@ int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) + + instruction_pointer_set(regs, utask->vaddr + auprobe->insn_size); + +- regs->status |= SR_SPIE; +- + return 0; + } + +@@ -111,8 +107,6 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) + * address. + */ + instruction_pointer_set(regs, utask->vaddr); +- +- regs->status &= ~SR_SPIE; + } + + bool arch_uretprobe_is_alive(struct return_instance *ret, enum rp_check ctx, +diff --git a/arch/riscv/kernel/reset.c b/arch/riscv/kernel/reset.c +index ee5878d968cc1..9c842c41684ac 100644 +--- a/arch/riscv/kernel/reset.c ++++ b/arch/riscv/kernel/reset.c +@@ -12,7 +12,7 @@ static void default_power_off(void) + wait_for_interrupt(); + } + +-void (*pm_power_off)(void) = default_power_off; ++void (*pm_power_off)(void) = NULL; + EXPORT_SYMBOL(pm_power_off); + + void machine_restart(char *cmd) +@@ -23,10 +23,16 @@ void machine_restart(char *cmd) + + void machine_halt(void) + { +- pm_power_off(); ++ if (pm_power_off != NULL) ++ pm_power_off(); ++ else ++ default_power_off(); + } + + void machine_power_off(void) + { +- pm_power_off(); ++ if (pm_power_off != NULL) ++ pm_power_off(); ++ else ++ default_power_off(); + } +diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c +index c58a7c77989b0..a37a08ceededd 100644 +--- a/arch/riscv/mm/init.c ++++ b/arch/riscv/mm/init.c +@@ -100,6 +100,10 @@ static void __init print_vm_layout(void) + (unsigned long)VMEMMAP_END); + print_mlm("vmalloc", (unsigned long)VMALLOC_START, + (unsigned long)VMALLOC_END); ++#ifdef CONFIG_64BIT ++ print_mlm("modules", (unsigned long)MODULES_VADDR, ++ (unsigned long)MODULES_END); ++#endif + print_mlm("lowmem", (unsigned long)PAGE_OFFSET, + (unsigned long)high_memory); + #ifdef CONFIG_64BIT +diff --git a/arch/s390/include/asm/ctl_reg.h b/arch/s390/include/asm/ctl_reg.h +index 04dc65f8901dc..80b93c06a2bbe 100644 +--- a/arch/s390/include/asm/ctl_reg.h ++++ b/arch/s390/include/asm/ctl_reg.h +@@ -72,8 +72,17 @@ static __always_inline void __ctl_clear_bit(unsigned int cr, unsigned int bit) + __ctl_load(reg, cr, cr); + } + +-void smp_ctl_set_bit(int cr, int bit); +-void smp_ctl_clear_bit(int cr, int bit); ++void smp_ctl_set_clear_bit(int cr, int bit, bool set); ++ ++static inline void ctl_set_bit(int cr, int bit) ++{ ++ smp_ctl_set_clear_bit(cr, bit, true); ++} ++ ++static inline void ctl_clear_bit(int cr, int bit) ++{ ++ smp_ctl_set_clear_bit(cr, bit, false); ++} + + union ctlreg0 { + unsigned long val; +@@ -128,8 +137,5 @@ union ctlreg15 { + }; + }; + +-#define ctl_set_bit(cr, bit) smp_ctl_set_bit(cr, bit) +-#define ctl_clear_bit(cr, bit) smp_ctl_clear_bit(cr, bit) +- + #endif /* __ASSEMBLY__ */ + #endif /* __ASM_CTL_REG_H */ +diff --git a/arch/s390/include/asm/gmap.h b/arch/s390/include/asm/gmap.h +index 40264f60b0da9..f4073106e1f39 100644 +--- a/arch/s390/include/asm/gmap.h ++++ b/arch/s390/include/asm/gmap.h +@@ -148,4 +148,6 @@ void gmap_sync_dirty_log_pmd(struct gmap *gmap, unsigned long dirty_bitmap[4], + unsigned long gaddr, unsigned long vmaddr); + int gmap_mark_unmergeable(void); + void s390_reset_acc(struct mm_struct *mm); ++void s390_unlist_old_asce(struct gmap *gmap); ++int s390_replace_asce(struct gmap *gmap); + #endif /* _ASM_S390_GMAP_H */ +diff --git a/arch/s390/include/asm/os_info.h b/arch/s390/include/asm/os_info.h +index 3c89279d2a4b1..147a8d547ef9e 100644 +--- a/arch/s390/include/asm/os_info.h ++++ b/arch/s390/include/asm/os_info.h +@@ -39,7 +39,7 @@ u32 os_info_csum(struct os_info *os_info); + + #ifdef CONFIG_CRASH_DUMP + void *os_info_old_entry(int nr, unsigned long *size); +-int copy_oldmem_kernel(void *dst, void *src, size_t count); ++int copy_oldmem_kernel(void *dst, unsigned long src, size_t count); + #else + static inline void *os_info_old_entry(int nr, unsigned long *size) + { +diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h +index 879b8e3f609cd..d7ca76bb2720f 100644 +--- a/arch/s390/include/asm/processor.h ++++ b/arch/s390/include/asm/processor.h +@@ -318,14 +318,21 @@ extern void (*s390_base_pgm_handler_fn)(void); + + #define ARCH_LOW_ADDRESS_LIMIT 0x7fffffffUL + +-extern int memcpy_real(void *, void *, size_t); ++extern int memcpy_real(void *, unsigned long, size_t); + extern void memcpy_absolute(void *, void *, size_t); + +-#define mem_assign_absolute(dest, val) do { \ +- __typeof__(dest) __tmp = (val); \ +- \ +- BUILD_BUG_ON(sizeof(__tmp) != sizeof(val)); \ +- memcpy_absolute(&(dest), &__tmp, sizeof(__tmp)); \ ++#define put_abs_lowcore(member, x) do { \ ++ unsigned long __abs_address = offsetof(struct lowcore, member); \ ++ __typeof__(((struct lowcore *)0)->member) __tmp = (x); \ ++ \ ++ memcpy_absolute(__va(__abs_address), &__tmp, sizeof(__tmp)); \ ++} while (0) ++ ++#define get_abs_lowcore(x, member) do { \ ++ unsigned long __abs_address = offsetof(struct lowcore, member); \ ++ __typeof__(((struct lowcore *)0)->member) *__ptr = &(x); \ ++ \ ++ memcpy_absolute(__ptr, __va(__abs_address), sizeof(*__ptr)); \ + } while (0) + + extern int s390_isolate_bp(void); +diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h +index ce550d06abc36..3379694e9a42f 100644 +--- a/arch/s390/include/asm/uaccess.h ++++ b/arch/s390/include/asm/uaccess.h +@@ -245,7 +245,7 @@ static inline unsigned long __must_check clear_user(void __user *to, unsigned lo + return __clear_user(to, n); + } + +-int copy_to_user_real(void __user *dest, void *src, unsigned long count); ++int copy_to_user_real(void __user *dest, unsigned long src, unsigned long count); + void *s390_kernel_write(void *dst, const void *src, size_t size); + + #define HAVE_GET_KERNEL_NOFAULT +diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c +index b57da93385888..9242d7ad71e79 100644 +--- a/arch/s390/kernel/asm-offsets.c ++++ b/arch/s390/kernel/asm-offsets.c +@@ -128,6 +128,8 @@ int main(void) + OFFSET(__LC_BR_R1, lowcore, br_r1_trampoline); + /* software defined ABI-relevant lowcore locations 0xe00 - 0xe20 */ + OFFSET(__LC_DUMP_REIPL, lowcore, ipib); ++ OFFSET(__LC_VMCORE_INFO, lowcore, vmcore_info); ++ OFFSET(__LC_OS_INFO, lowcore, os_info); + /* hardware defined lowcore locations 0x1000 - 0x18ff */ + OFFSET(__LC_MCESAD, lowcore, mcesad); + OFFSET(__LC_EXT_PARAMS2, lowcore, ext_params2); +diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c +index 785d54c9350c4..f17ad2daab079 100644 +--- a/arch/s390/kernel/crash_dump.c ++++ b/arch/s390/kernel/crash_dump.c +@@ -132,28 +132,27 @@ static inline void *load_real_addr(void *addr) + /* + * Copy memory of the old, dumped system to a kernel space virtual address + */ +-int copy_oldmem_kernel(void *dst, void *src, size_t count) ++int copy_oldmem_kernel(void *dst, unsigned long src, size_t count) + { +- unsigned long from, len; ++ unsigned long len; + void *ra; + int rc; + + while (count) { +- from = __pa(src); +- if (!oldmem_data.start && from < sclp.hsa_size) { ++ if (!oldmem_data.start && src < sclp.hsa_size) { + /* Copy from zfcp/nvme dump HSA area */ +- len = min(count, sclp.hsa_size - from); +- rc = memcpy_hsa_kernel(dst, from, len); ++ len = min(count, sclp.hsa_size - src); ++ rc = memcpy_hsa_kernel(dst, src, len); + if (rc) + return rc; + } else { + /* Check for swapped kdump oldmem areas */ +- if (oldmem_data.start && from - oldmem_data.start < oldmem_data.size) { +- from -= oldmem_data.start; +- len = min(count, oldmem_data.size - from); +- } else if (oldmem_data.start && from < oldmem_data.size) { +- len = min(count, oldmem_data.size - from); +- from += oldmem_data.start; ++ if (oldmem_data.start && src - oldmem_data.start < oldmem_data.size) { ++ src -= oldmem_data.start; ++ len = min(count, oldmem_data.size - src); ++ } else if (oldmem_data.start && src < oldmem_data.size) { ++ len = min(count, oldmem_data.size - src); ++ src += oldmem_data.start; + } else { + len = count; + } +@@ -163,7 +162,7 @@ int copy_oldmem_kernel(void *dst, void *src, size_t count) + } else { + ra = dst; + } +- if (memcpy_real(ra, (void *) from, len)) ++ if (memcpy_real(ra, src, len)) + return -EFAULT; + } + dst += len; +@@ -176,31 +175,30 @@ int copy_oldmem_kernel(void *dst, void *src, size_t count) + /* + * Copy memory of the old, dumped system to a user space virtual address + */ +-static int copy_oldmem_user(void __user *dst, void *src, size_t count) ++static int copy_oldmem_user(void __user *dst, unsigned long src, size_t count) + { +- unsigned long from, len; ++ unsigned long len; + int rc; + + while (count) { +- from = __pa(src); +- if (!oldmem_data.start && from < sclp.hsa_size) { ++ if (!oldmem_data.start && src < sclp.hsa_size) { + /* Copy from zfcp/nvme dump HSA area */ +- len = min(count, sclp.hsa_size - from); +- rc = memcpy_hsa_user(dst, from, len); ++ len = min(count, sclp.hsa_size - src); ++ rc = memcpy_hsa_user(dst, src, len); + if (rc) + return rc; + } else { + /* Check for swapped kdump oldmem areas */ +- if (oldmem_data.start && from - oldmem_data.start < oldmem_data.size) { +- from -= oldmem_data.start; +- len = min(count, oldmem_data.size - from); +- } else if (oldmem_data.start && from < oldmem_data.size) { +- len = min(count, oldmem_data.size - from); +- from += oldmem_data.start; ++ if (oldmem_data.start && src - oldmem_data.start < oldmem_data.size) { ++ src -= oldmem_data.start; ++ len = min(count, oldmem_data.size - src); ++ } else if (oldmem_data.start && src < oldmem_data.size) { ++ len = min(count, oldmem_data.size - src); ++ src += oldmem_data.start; + } else { + len = count; + } +- rc = copy_to_user_real(dst, (void *) from, count); ++ rc = copy_to_user_real(dst, src, len); + if (rc) + return rc; + } +@@ -217,12 +215,12 @@ static int copy_oldmem_user(void __user *dst, void *src, size_t count) + ssize_t copy_oldmem_page(unsigned long pfn, char *buf, size_t csize, + unsigned long offset, int userbuf) + { +- void *src; ++ unsigned long src; + int rc; + + if (!csize) + return 0; +- src = (void *) (pfn << PAGE_SHIFT) + offset; ++ src = pfn_to_phys(pfn) + offset; + if (userbuf) + rc = copy_oldmem_user((void __force __user *) buf, src, csize); + else +@@ -429,10 +427,10 @@ static void *nt_prpsinfo(void *ptr) + static void *get_vmcoreinfo_old(unsigned long *size) + { + char nt_name[11], *vmcoreinfo; ++ unsigned long addr; + Elf64_Nhdr note; +- void *addr; + +- if (copy_oldmem_kernel(&addr, &S390_lowcore.vmcore_info, sizeof(addr))) ++ if (copy_oldmem_kernel(&addr, __LC_VMCORE_INFO, sizeof(addr))) + return NULL; + memset(nt_name, 0, sizeof(nt_name)); + if (copy_oldmem_kernel(¬e, addr, sizeof(note))) +diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c +index 5ad1dde23dc59..ba2988783d664 100644 +--- a/arch/s390/kernel/ipl.c ++++ b/arch/s390/kernel/ipl.c +@@ -1646,8 +1646,8 @@ static void dump_reipl_run(struct shutdown_trigger *trigger) + + csum = (__force unsigned int) + csum_partial(reipl_block_actual, reipl_block_actual->hdr.len, 0); +- mem_assign_absolute(S390_lowcore.ipib, ipib); +- mem_assign_absolute(S390_lowcore.ipib_checksum, csum); ++ put_abs_lowcore(ipib, ipib); ++ put_abs_lowcore(ipib_checksum, csum); + dump_run(trigger); + } + +diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c +index 0505e55a62979..4b95684fbe46e 100644 +--- a/arch/s390/kernel/machine_kexec.c ++++ b/arch/s390/kernel/machine_kexec.c +@@ -227,7 +227,7 @@ void arch_crash_save_vmcoreinfo(void) + vmcoreinfo_append_str("SAMODE31=%lx\n", __samode31); + vmcoreinfo_append_str("EAMODE31=%lx\n", __eamode31); + vmcoreinfo_append_str("KERNELOFFSET=%lx\n", kaslr_offset()); +- mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note()); ++ put_abs_lowcore(vmcore_info, paddr_vmcoreinfo_note()); + } + + void machine_shutdown(void) +diff --git a/arch/s390/kernel/machine_kexec_file.c b/arch/s390/kernel/machine_kexec_file.c +index a81d6c43b9b61..3459362c54ac3 100644 +--- a/arch/s390/kernel/machine_kexec_file.c ++++ b/arch/s390/kernel/machine_kexec_file.c +@@ -29,6 +29,7 @@ int s390_verify_sig(const char *kernel, unsigned long kernel_len) + const unsigned long marker_len = sizeof(MODULE_SIG_STRING) - 1; + struct module_signature *ms; + unsigned long sig_len; ++ int ret; + + /* Skip signature verification when not secure IPLed. */ + if (!ipl_secure_flag) +@@ -63,11 +64,18 @@ int s390_verify_sig(const char *kernel, unsigned long kernel_len) + return -EBADMSG; + } + +- return verify_pkcs7_signature(kernel, kernel_len, +- kernel + kernel_len, sig_len, +- VERIFY_USE_PLATFORM_KEYRING, +- VERIFYING_MODULE_SIGNATURE, +- NULL, NULL); ++ ret = verify_pkcs7_signature(kernel, kernel_len, ++ kernel + kernel_len, sig_len, ++ VERIFY_USE_SECONDARY_KEYRING, ++ VERIFYING_MODULE_SIGNATURE, ++ NULL, NULL); ++ if (ret == -ENOKEY && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING)) ++ ret = verify_pkcs7_signature(kernel, kernel_len, ++ kernel + kernel_len, sig_len, ++ VERIFY_USE_PLATFORM_KEYRING, ++ VERIFYING_MODULE_SIGNATURE, ++ NULL, NULL); ++ return ret; + } + #endif /* CONFIG_KEXEC_SIG */ + +diff --git a/arch/s390/kernel/os_info.c b/arch/s390/kernel/os_info.c +index 4bef35b79b938..1acc2e05d70f0 100644 +--- a/arch/s390/kernel/os_info.c ++++ b/arch/s390/kernel/os_info.c +@@ -15,6 +15,7 @@ + #include <asm/checksum.h> + #include <asm/lowcore.h> + #include <asm/os_info.h> ++#include <asm/asm-offsets.h> + + /* + * OS info structure has to be page aligned +@@ -45,7 +46,7 @@ void os_info_crashkernel_add(unsigned long base, unsigned long size) + */ + void os_info_entry_add(int nr, void *ptr, u64 size) + { +- os_info.entry[nr].addr = (u64)(unsigned long)ptr; ++ os_info.entry[nr].addr = __pa(ptr); + os_info.entry[nr].size = size; + os_info.entry[nr].csum = (__force u32)csum_partial(ptr, size, 0); + os_info.csum = os_info_csum(&os_info); +@@ -62,7 +63,7 @@ void __init os_info_init(void) + os_info.version_minor = OS_INFO_VERSION_MINOR; + os_info.magic = OS_INFO_MAGIC; + os_info.csum = os_info_csum(&os_info); +- mem_assign_absolute(S390_lowcore.os_info, (unsigned long) ptr); ++ put_abs_lowcore(os_info, __pa(ptr)); + } + + #ifdef CONFIG_CRASH_DUMP +@@ -90,7 +91,7 @@ static void os_info_old_alloc(int nr, int align) + goto fail; + } + buf_align = PTR_ALIGN(buf, align); +- if (copy_oldmem_kernel(buf_align, (void *) addr, size)) { ++ if (copy_oldmem_kernel(buf_align, addr, size)) { + msg = "copy failed"; + goto fail_free; + } +@@ -123,15 +124,14 @@ static void os_info_old_init(void) + return; + if (!oldmem_data.start) + goto fail; +- if (copy_oldmem_kernel(&addr, &S390_lowcore.os_info, sizeof(addr))) ++ if (copy_oldmem_kernel(&addr, __LC_OS_INFO, sizeof(addr))) + goto fail; + if (addr == 0 || addr % PAGE_SIZE) + goto fail; + os_info_old = kzalloc(sizeof(*os_info_old), GFP_KERNEL); + if (!os_info_old) + goto fail; +- if (copy_oldmem_kernel(os_info_old, (void *) addr, +- sizeof(*os_info_old))) ++ if (copy_oldmem_kernel(os_info_old, addr, sizeof(*os_info_old))) + goto fail_free; + if (os_info_old->magic != OS_INFO_MAGIC) + goto fail_free; +diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c +index 36c1f31dfd66f..6b1a8697fae8d 100644 +--- a/arch/s390/kernel/setup.c ++++ b/arch/s390/kernel/setup.c +@@ -479,11 +479,11 @@ static void __init setup_lowcore_dat_off(void) + lc->mcck_stack = mcck_stack + STACK_INIT_OFFSET; + + /* Setup absolute zero lowcore */ +- mem_assign_absolute(S390_lowcore.restart_stack, lc->restart_stack); +- mem_assign_absolute(S390_lowcore.restart_fn, lc->restart_fn); +- mem_assign_absolute(S390_lowcore.restart_data, lc->restart_data); +- mem_assign_absolute(S390_lowcore.restart_source, lc->restart_source); +- mem_assign_absolute(S390_lowcore.restart_psw, lc->restart_psw); ++ put_abs_lowcore(restart_stack, lc->restart_stack); ++ put_abs_lowcore(restart_fn, lc->restart_fn); ++ put_abs_lowcore(restart_data, lc->restart_data); ++ put_abs_lowcore(restart_source, lc->restart_source); ++ put_abs_lowcore(restart_psw, lc->restart_psw); + + lc->spinlock_lockval = arch_spin_lockval(0); + lc->spinlock_index = 0; +@@ -500,6 +500,7 @@ static void __init setup_lowcore_dat_off(void) + static void __init setup_lowcore_dat_on(void) + { + struct lowcore *lc = lowcore_ptr[0]; ++ int cr; + + __ctl_clear_bit(0, 28); + S390_lowcore.external_new_psw.mask |= PSW_MASK_DAT; +@@ -508,10 +509,10 @@ static void __init setup_lowcore_dat_on(void) + S390_lowcore.io_new_psw.mask |= PSW_MASK_DAT; + __ctl_store(S390_lowcore.cregs_save_area, 0, 15); + __ctl_set_bit(0, 28); +- mem_assign_absolute(S390_lowcore.restart_flags, RESTART_FLAG_CTLREGS); +- mem_assign_absolute(S390_lowcore.program_new_psw, lc->program_new_psw); +- memcpy_absolute(&S390_lowcore.cregs_save_area, lc->cregs_save_area, +- sizeof(S390_lowcore.cregs_save_area)); ++ put_abs_lowcore(restart_flags, RESTART_FLAG_CTLREGS); ++ put_abs_lowcore(program_new_psw, lc->program_new_psw); ++ for (cr = 0; cr < ARRAY_SIZE(lc->cregs_save_area); cr++) ++ put_abs_lowcore(cregs_save_area[cr], lc->cregs_save_area[cr]); + } + + static struct resource code_resource = { +diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c +index 1a04e5bdf6555..35af70ed58fc7 100644 +--- a/arch/s390/kernel/smp.c ++++ b/arch/s390/kernel/smp.c +@@ -328,10 +328,17 @@ static void pcpu_delegate(struct pcpu *pcpu, + /* Stop target cpu (if func returns this stops the current cpu). */ + pcpu_sigp_retry(pcpu, SIGP_STOP, 0); + /* Restart func on the target cpu and stop the current cpu. */ +- mem_assign_absolute(lc->restart_stack, stack); +- mem_assign_absolute(lc->restart_fn, (unsigned long) func); +- mem_assign_absolute(lc->restart_data, (unsigned long) data); +- mem_assign_absolute(lc->restart_source, source_cpu); ++ if (lc) { ++ lc->restart_stack = stack; ++ lc->restart_fn = (unsigned long)func; ++ lc->restart_data = (unsigned long)data; ++ lc->restart_source = source_cpu; ++ } else { ++ put_abs_lowcore(restart_stack, stack); ++ put_abs_lowcore(restart_fn, (unsigned long)func); ++ put_abs_lowcore(restart_data, (unsigned long)data); ++ put_abs_lowcore(restart_source, source_cpu); ++ } + __bpon(); + asm volatile( + "0: sigp 0,%0,%2 # sigp restart to target cpu\n" +@@ -572,39 +579,27 @@ static void smp_ctl_bit_callback(void *info) + } + + static DEFINE_SPINLOCK(ctl_lock); +-static unsigned long ctlreg; + +-/* +- * Set a bit in a control register of all cpus +- */ +-void smp_ctl_set_bit(int cr, int bit) ++void smp_ctl_set_clear_bit(int cr, int bit, bool set) + { +- struct ec_creg_mask_parms parms = { 1UL << bit, -1UL, cr }; +- +- spin_lock(&ctl_lock); +- memcpy_absolute(&ctlreg, &S390_lowcore.cregs_save_area[cr], sizeof(ctlreg)); +- __set_bit(bit, &ctlreg); +- memcpy_absolute(&S390_lowcore.cregs_save_area[cr], &ctlreg, sizeof(ctlreg)); +- spin_unlock(&ctl_lock); +- on_each_cpu(smp_ctl_bit_callback, &parms, 1); +-} +-EXPORT_SYMBOL(smp_ctl_set_bit); +- +-/* +- * Clear a bit in a control register of all cpus +- */ +-void smp_ctl_clear_bit(int cr, int bit) +-{ +- struct ec_creg_mask_parms parms = { 0, ~(1UL << bit), cr }; ++ struct ec_creg_mask_parms parms = { .cr = cr, }; ++ u64 ctlreg; + ++ if (set) { ++ parms.orval = 1UL << bit; ++ parms.andval = -1UL; ++ } else { ++ parms.orval = 0; ++ parms.andval = ~(1UL << bit); ++ } + spin_lock(&ctl_lock); +- memcpy_absolute(&ctlreg, &S390_lowcore.cregs_save_area[cr], sizeof(ctlreg)); +- __clear_bit(bit, &ctlreg); +- memcpy_absolute(&S390_lowcore.cregs_save_area[cr], &ctlreg, sizeof(ctlreg)); ++ get_abs_lowcore(ctlreg, cregs_save_area[cr]); ++ ctlreg = (ctlreg & parms.andval) | parms.orval; ++ put_abs_lowcore(cregs_save_area[cr], ctlreg); + spin_unlock(&ctl_lock); + on_each_cpu(smp_ctl_bit_callback, &parms, 1); + } +-EXPORT_SYMBOL(smp_ctl_clear_bit); ++EXPORT_SYMBOL(smp_ctl_set_clear_bit); + + #ifdef CONFIG_CRASH_DUMP + +@@ -675,7 +670,7 @@ static __init void smp_save_cpu_regs(struct save_area *sa, u16 addr, + void *regs = (void *) page; + + if (is_boot_cpu) +- copy_oldmem_kernel(regs, (void *) __LC_FPREGS_SAVE_AREA, 512); ++ copy_oldmem_kernel(regs, __LC_FPREGS_SAVE_AREA, 512); + else + __pcpu_sigp_relax(addr, SIGP_STORE_STATUS_AT_ADDRESS, page); + save_area_add_regs(sa, regs); +diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c +index 2bd8f854f1b41..8ca301f49b305 100644 +--- a/arch/s390/kvm/intercept.c ++++ b/arch/s390/kvm/intercept.c +@@ -523,12 +523,27 @@ static int handle_pv_uvc(struct kvm_vcpu *vcpu) + + static int handle_pv_notification(struct kvm_vcpu *vcpu) + { ++ int ret; ++ + if (vcpu->arch.sie_block->ipa == 0xb210) + return handle_pv_spx(vcpu); + if (vcpu->arch.sie_block->ipa == 0xb220) + return handle_pv_sclp(vcpu); + if (vcpu->arch.sie_block->ipa == 0xb9a4) + return handle_pv_uvc(vcpu); ++ if (vcpu->arch.sie_block->ipa >> 8 == 0xae) { ++ /* ++ * Besides external call, other SIGP orders also cause a ++ * 108 (pv notify) intercept. In contrast to external call, ++ * these orders need to be emulated and hence the appropriate ++ * place to handle them is in handle_instruction(). ++ * So first try kvm_s390_handle_sigp_pei() and if that isn't ++ * successful, go on with handle_instruction(). ++ */ ++ ret = kvm_s390_handle_sigp_pei(vcpu); ++ if (!ret) ++ return ret; ++ } + + return handle_instruction(vcpu); + } +diff --git a/arch/s390/kvm/pv.c b/arch/s390/kvm/pv.c +index 00d272d134c24..b906658ffc2ed 100644 +--- a/arch/s390/kvm/pv.c ++++ b/arch/s390/kvm/pv.c +@@ -168,10 +168,13 @@ int kvm_s390_pv_deinit_vm(struct kvm *kvm, u16 *rc, u16 *rrc) + atomic_set(&kvm->mm->context.is_protected, 0); + KVM_UV_EVENT(kvm, 3, "PROTVIRT DESTROY VM: rc %x rrc %x", *rc, *rrc); + WARN_ONCE(cc, "protvirt destroy vm failed rc %x rrc %x", *rc, *rrc); +- /* Inteded memory leak on "impossible" error */ +- if (!cc) ++ /* Intended memory leak on "impossible" error */ ++ if (!cc) { + kvm_s390_pv_dealloc_vm(kvm); +- return cc ? -EIO : 0; ++ return 0; ++ } ++ s390_replace_asce(kvm->arch.gmap); ++ return -EIO; + } + + int kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc) +diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c +index 3dc921e853b6e..52800279686c0 100644 +--- a/arch/s390/kvm/sigp.c ++++ b/arch/s390/kvm/sigp.c +@@ -492,9 +492,9 @@ int kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu) + struct kvm_vcpu *dest_vcpu; + u8 order_code = kvm_s390_get_base_disp_rs(vcpu, NULL); + +- trace_kvm_s390_handle_sigp_pei(vcpu, order_code, cpu_addr); +- + if (order_code == SIGP_EXTERNAL_CALL) { ++ trace_kvm_s390_handle_sigp_pei(vcpu, order_code, cpu_addr); ++ + dest_vcpu = kvm_get_vcpu_by_id(vcpu->kvm, cpu_addr); + BUG_ON(dest_vcpu == NULL); + +diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c +index 4ce3a2f01c917..ff40bf92db43a 100644 +--- a/arch/s390/mm/gmap.c ++++ b/arch/s390/mm/gmap.c +@@ -2726,3 +2726,89 @@ void s390_reset_acc(struct mm_struct *mm) + mmput(mm); + } + EXPORT_SYMBOL_GPL(s390_reset_acc); ++ ++/** ++ * s390_unlist_old_asce - Remove the topmost level of page tables from the ++ * list of page tables of the gmap. ++ * @gmap: the gmap whose table is to be removed ++ * ++ * On s390x, KVM keeps a list of all pages containing the page tables of the ++ * gmap (the CRST list). This list is used at tear down time to free all ++ * pages that are now not needed anymore. ++ * ++ * This function removes the topmost page of the tree (the one pointed to by ++ * the ASCE) from the CRST list. ++ * ++ * This means that it will not be freed when the VM is torn down, and needs ++ * to be handled separately by the caller, unless a leak is actually ++ * intended. Notice that this function will only remove the page from the ++ * list, the page will still be used as a top level page table (and ASCE). ++ */ ++void s390_unlist_old_asce(struct gmap *gmap) ++{ ++ struct page *old; ++ ++ old = virt_to_page(gmap->table); ++ spin_lock(&gmap->guest_table_lock); ++ list_del(&old->lru); ++ /* ++ * Sometimes the topmost page might need to be "removed" multiple ++ * times, for example if the VM is rebooted into secure mode several ++ * times concurrently, or if s390_replace_asce fails after calling ++ * s390_remove_old_asce and is attempted again later. In that case ++ * the old asce has been removed from the list, and therefore it ++ * will not be freed when the VM terminates, but the ASCE is still ++ * in use and still pointed to. ++ * A subsequent call to replace_asce will follow the pointer and try ++ * to remove the same page from the list again. ++ * Therefore it's necessary that the page of the ASCE has valid ++ * pointers, so list_del can work (and do nothing) without ++ * dereferencing stale or invalid pointers. ++ */ ++ INIT_LIST_HEAD(&old->lru); ++ spin_unlock(&gmap->guest_table_lock); ++} ++EXPORT_SYMBOL_GPL(s390_unlist_old_asce); ++ ++/** ++ * s390_replace_asce - Try to replace the current ASCE of a gmap with a copy ++ * @gmap: the gmap whose ASCE needs to be replaced ++ * ++ * If the allocation of the new top level page table fails, the ASCE is not ++ * replaced. ++ * In any case, the old ASCE is always removed from the gmap CRST list. ++ * Therefore the caller has to make sure to save a pointer to it ++ * beforehand, unless a leak is actually intended. ++ */ ++int s390_replace_asce(struct gmap *gmap) ++{ ++ unsigned long asce; ++ struct page *page; ++ void *table; ++ ++ s390_unlist_old_asce(gmap); ++ ++ page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER); ++ if (!page) ++ return -ENOMEM; ++ table = page_to_virt(page); ++ memcpy(table, gmap->table, 1UL << (CRST_ALLOC_ORDER + PAGE_SHIFT)); ++ ++ /* ++ * The caller has to deal with the old ASCE, but here we make sure ++ * the new one is properly added to the CRST list, so that ++ * it will be freed when the VM is torn down. ++ */ ++ spin_lock(&gmap->guest_table_lock); ++ list_add(&page->lru, &gmap->crst_list); ++ spin_unlock(&gmap->guest_table_lock); ++ ++ /* Set new table origin while preserving existing ASCE control bits */ ++ asce = (gmap->asce & ~_ASCE_ORIGIN) | __pa(table); ++ WRITE_ONCE(gmap->asce, asce); ++ WRITE_ONCE(gmap->mm->context.gmap_asce, asce); ++ WRITE_ONCE(gmap->table, table); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(s390_replace_asce); +diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c +index 9663ce3625bcd..2ed198b4f7d02 100644 +--- a/arch/s390/mm/maccess.c ++++ b/arch/s390/mm/maccess.c +@@ -123,7 +123,7 @@ static unsigned long __no_sanitize_address _memcpy_real(unsigned long dest, + /* + * Copy memory in real mode (kernel to kernel) + */ +-int memcpy_real(void *dest, void *src, size_t count) ++int memcpy_real(void *dest, unsigned long src, size_t count) + { + unsigned long _dest = (unsigned long)dest; + unsigned long _src = (unsigned long)src; +@@ -175,7 +175,7 @@ void memcpy_absolute(void *dest, void *src, size_t count) + /* + * Copy memory from kernel (real) to user (virtual) + */ +-int copy_to_user_real(void __user *dest, void *src, unsigned long count) ++int copy_to_user_real(void __user *dest, unsigned long src, unsigned long count) + { + int offs = 0, size, rc; + char *buf; +diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c +index 433a3f8f2ef3e..32b3341fe9707 100644 +--- a/arch/um/drivers/random.c ++++ b/arch/um/drivers/random.c +@@ -28,7 +28,7 @@ + * protects against a module being loaded twice at the same time. + */ + static int random_fd = -1; +-static struct hwrng hwrng = { 0, }; ++static struct hwrng hwrng; + static DECLARE_COMPLETION(have_data); + + static int rng_dev_read(struct hwrng *rng, void *buf, size_t max, bool block) +diff --git a/arch/um/include/asm/archrandom.h b/arch/um/include/asm/archrandom.h +new file mode 100644 +index 0000000000000..2f24cb96391d7 +--- /dev/null ++++ b/arch/um/include/asm/archrandom.h +@@ -0,0 +1,30 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef __ASM_UM_ARCHRANDOM_H__ ++#define __ASM_UM_ARCHRANDOM_H__ ++ ++#include <linux/types.h> ++ ++/* This is from <os.h>, but better not to #include that in a global header here. */ ++ssize_t os_getrandom(void *buf, size_t len, unsigned int flags); ++ ++static inline bool __must_check arch_get_random_long(unsigned long *v) ++{ ++ return os_getrandom(v, sizeof(*v), 0) == sizeof(*v); ++} ++ ++static inline bool __must_check arch_get_random_int(unsigned int *v) ++{ ++ return os_getrandom(v, sizeof(*v), 0) == sizeof(*v); ++} ++ ++static inline bool __must_check arch_get_random_seed_long(unsigned long *v) ++{ ++ return false; ++} ++ ++static inline bool __must_check arch_get_random_seed_int(unsigned int *v) ++{ ++ return false; ++} ++ ++#endif +diff --git a/arch/um/include/asm/xor.h b/arch/um/include/asm/xor.h +index 22b39de73c246..647fae200c5d3 100644 +--- a/arch/um/include/asm/xor.h ++++ b/arch/um/include/asm/xor.h +@@ -18,7 +18,7 @@ + #undef XOR_SELECT_TEMPLATE + /* pick an arbitrary one - measuring isn't possible with inf-cpu */ + #define XOR_SELECT_TEMPLATE(x) \ +- (time_travel_mode == TT_MODE_INFCPU ? TT_CPU_INF_XOR_DEFAULT : x)) ++ (time_travel_mode == TT_MODE_INFCPU ? TT_CPU_INF_XOR_DEFAULT : x) + #endif + + #endif +diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h +index 03ffbdddcc480..90e9c9f86f15c 100644 +--- a/arch/um/include/shared/os.h ++++ b/arch/um/include/shared/os.h +@@ -11,6 +11,12 @@ + #include <irq_user.h> + #include <longjmp.h> + #include <mm_id.h> ++/* This is to get size_t */ ++#ifndef __UM_HOST__ ++#include <linux/types.h> ++#else ++#include <sys/types.h> ++#endif + + #define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR)) + +@@ -252,6 +258,7 @@ extern void stack_protections(unsigned long address); + extern int raw(int fd); + extern void setup_machinename(char *machine_out); + extern void setup_hostinfo(char *buf, int len); ++extern ssize_t os_getrandom(void *buf, size_t len, unsigned int flags); + extern void os_dump_core(void) __attribute__ ((noreturn)); + extern void um_early_printk(const char *s, unsigned int n); + extern void os_fix_helper_signals(void); +diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c +index 5aa5e7533b757..960f5c35ad1b6 100644 +--- a/arch/um/kernel/um_arch.c ++++ b/arch/um/kernel/um_arch.c +@@ -16,6 +16,7 @@ + #include <linux/sched/task.h> + #include <linux/kmsg_dump.h> + #include <linux/suspend.h> ++#include <linux/random.h> + + #include <asm/processor.h> + #include <asm/cpufeature.h> +@@ -404,6 +405,8 @@ int __init __weak read_initrd(void) + + void __init setup_arch(char **cmdline_p) + { ++ u8 rng_seed[32]; ++ + stack_protections((unsigned long) &init_thread_info); + setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); + mem_total_pages(physmem_size, iomem_size, highmem); +@@ -413,6 +416,11 @@ void __init setup_arch(char **cmdline_p) + strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); + *cmdline_p = command_line; + setup_hostinfo(host_info, sizeof host_info); ++ ++ if (os_getrandom(rng_seed, sizeof(rng_seed), 0) == sizeof(rng_seed)) { ++ add_bootloader_randomness(rng_seed, sizeof(rng_seed)); ++ memzero_explicit(rng_seed, sizeof(rng_seed)); ++ } + } + + void __init check_bugs(void) +diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c +index 41297ec404bf9..fc0f2a9dee5af 100644 +--- a/arch/um/os-Linux/util.c ++++ b/arch/um/os-Linux/util.c +@@ -14,6 +14,7 @@ + #include <sys/wait.h> + #include <sys/mman.h> + #include <sys/utsname.h> ++#include <sys/random.h> + #include <init.h> + #include <os.h> + +@@ -96,6 +97,11 @@ static inline void __attribute__ ((noreturn)) uml_abort(void) + exit(127); + } + ++ssize_t os_getrandom(void *buf, size_t len, unsigned int flags) ++{ ++ return getrandom(buf, len, flags); ++} ++ + /* + * UML helper threads must not handle SIGWINCH/INT/TERM + */ +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index fe6981a387957..57f5e881791a4 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -260,6 +260,7 @@ config X86 + select SYSCTL_EXCEPTION_TRACE + select THREAD_INFO_IN_TASK + select TRACE_IRQFLAGS_SUPPORT ++ select TRACE_IRQFLAGS_NMI_SUPPORT + select USER_STACKTRACE_SUPPORT + select VIRT_TO_BUS + select HAVE_ARCH_KCSAN if X86_64 +diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug +index d3a6f74a94bdf..d4d6db4dde220 100644 +--- a/arch/x86/Kconfig.debug ++++ b/arch/x86/Kconfig.debug +@@ -1,8 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0 + +-config TRACE_IRQFLAGS_NMI_SUPPORT +- def_bool y +- + config EARLY_PRINTK_USB + bool + +diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile +index b5aecb524a8aa..ffec8bb01ba8c 100644 +--- a/arch/x86/boot/Makefile ++++ b/arch/x86/boot/Makefile +@@ -103,7 +103,7 @@ $(obj)/zoffset.h: $(obj)/compressed/vmlinux FORCE + AFLAGS_header.o += -I$(objtree)/$(obj) + $(obj)/header.o: $(obj)/zoffset.h + +-LDFLAGS_setup.elf := -m elf_i386 -T ++LDFLAGS_setup.elf := -m elf_i386 -z noexecstack -T + $(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE + $(call if_changed,ld) + +diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile +index e118136460518..15c5ae62a0e94 100644 +--- a/arch/x86/boot/compressed/Makefile ++++ b/arch/x86/boot/compressed/Makefile +@@ -69,6 +69,10 @@ LDFLAGS_vmlinux := -pie $(call ld-option, --no-dynamic-linker) + ifdef CONFIG_LD_ORPHAN_WARN + LDFLAGS_vmlinux += --orphan-handling=warn + endif ++LDFLAGS_vmlinux += -z noexecstack ++ifeq ($(CONFIG_LD_IS_BFD),y) ++LDFLAGS_vmlinux += $(call ld-option,--no-warn-rwx-segments) ++endif + LDFLAGS_vmlinux += -T + + hostprogs := mkpiggy +diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile +index c3af959648e62..fce05e9df56db 100644 +--- a/arch/x86/crypto/Makefile ++++ b/arch/x86/crypto/Makefile +@@ -61,9 +61,7 @@ sha256-ssse3-$(CONFIG_AS_SHA256_NI) += sha256_ni_asm.o + obj-$(CONFIG_CRYPTO_SHA512_SSSE3) += sha512-ssse3.o + sha512-ssse3-y := sha512-ssse3-asm.o sha512-avx-asm.o sha512-avx2-asm.o sha512_ssse3_glue.o + +-obj-$(CONFIG_CRYPTO_BLAKE2S_X86) += blake2s-x86_64.o +-blake2s-x86_64-y := blake2s-shash.o +-obj-$(if $(CONFIG_CRYPTO_BLAKE2S_X86),y) += libblake2s-x86_64.o ++obj-$(CONFIG_CRYPTO_BLAKE2S_X86) += libblake2s-x86_64.o + libblake2s-x86_64-y := blake2s-core.o blake2s-glue.o + + obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o +diff --git a/arch/x86/crypto/blake2s-glue.c b/arch/x86/crypto/blake2s-glue.c +index 69853c13e8fb0..aaba212305288 100644 +--- a/arch/x86/crypto/blake2s-glue.c ++++ b/arch/x86/crypto/blake2s-glue.c +@@ -4,7 +4,6 @@ + */ + + #include <crypto/internal/blake2s.h> +-#include <crypto/internal/simd.h> + + #include <linux/types.h> + #include <linux/jump_label.h> +@@ -33,7 +32,7 @@ void blake2s_compress(struct blake2s_state *state, const u8 *block, + /* SIMD disables preemption, so relax after processing each page. */ + BUILD_BUG_ON(SZ_4K / BLAKE2S_BLOCK_SIZE < 8); + +- if (!static_branch_likely(&blake2s_use_ssse3) || !crypto_simd_usable()) { ++ if (!static_branch_likely(&blake2s_use_ssse3) || !may_use_simd()) { + blake2s_compress_generic(state, block, nblocks, inc); + return; + } +diff --git a/arch/x86/crypto/blake2s-shash.c b/arch/x86/crypto/blake2s-shash.c +deleted file mode 100644 +index 59ae28abe35cc..0000000000000 +--- a/arch/x86/crypto/blake2s-shash.c ++++ /dev/null +@@ -1,77 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 OR MIT +-/* +- * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. +- */ +- +-#include <crypto/internal/blake2s.h> +-#include <crypto/internal/simd.h> +-#include <crypto/internal/hash.h> +- +-#include <linux/types.h> +-#include <linux/kernel.h> +-#include <linux/module.h> +-#include <linux/sizes.h> +- +-#include <asm/cpufeature.h> +-#include <asm/processor.h> +- +-static int crypto_blake2s_update_x86(struct shash_desc *desc, +- const u8 *in, unsigned int inlen) +-{ +- return crypto_blake2s_update(desc, in, inlen, false); +-} +- +-static int crypto_blake2s_final_x86(struct shash_desc *desc, u8 *out) +-{ +- return crypto_blake2s_final(desc, out, false); +-} +- +-#define BLAKE2S_ALG(name, driver_name, digest_size) \ +- { \ +- .base.cra_name = name, \ +- .base.cra_driver_name = driver_name, \ +- .base.cra_priority = 200, \ +- .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, \ +- .base.cra_blocksize = BLAKE2S_BLOCK_SIZE, \ +- .base.cra_ctxsize = sizeof(struct blake2s_tfm_ctx), \ +- .base.cra_module = THIS_MODULE, \ +- .digestsize = digest_size, \ +- .setkey = crypto_blake2s_setkey, \ +- .init = crypto_blake2s_init, \ +- .update = crypto_blake2s_update_x86, \ +- .final = crypto_blake2s_final_x86, \ +- .descsize = sizeof(struct blake2s_state), \ +- } +- +-static struct shash_alg blake2s_algs[] = { +- BLAKE2S_ALG("blake2s-128", "blake2s-128-x86", BLAKE2S_128_HASH_SIZE), +- BLAKE2S_ALG("blake2s-160", "blake2s-160-x86", BLAKE2S_160_HASH_SIZE), +- BLAKE2S_ALG("blake2s-224", "blake2s-224-x86", BLAKE2S_224_HASH_SIZE), +- BLAKE2S_ALG("blake2s-256", "blake2s-256-x86", BLAKE2S_256_HASH_SIZE), +-}; +- +-static int __init blake2s_mod_init(void) +-{ +- if (IS_REACHABLE(CONFIG_CRYPTO_HASH) && boot_cpu_has(X86_FEATURE_SSSE3)) +- return crypto_register_shashes(blake2s_algs, ARRAY_SIZE(blake2s_algs)); +- return 0; +-} +- +-static void __exit blake2s_mod_exit(void) +-{ +- if (IS_REACHABLE(CONFIG_CRYPTO_HASH) && boot_cpu_has(X86_FEATURE_SSSE3)) +- crypto_unregister_shashes(blake2s_algs, ARRAY_SIZE(blake2s_algs)); +-} +- +-module_init(blake2s_mod_init); +-module_exit(blake2s_mod_exit); +- +-MODULE_ALIAS_CRYPTO("blake2s-128"); +-MODULE_ALIAS_CRYPTO("blake2s-128-x86"); +-MODULE_ALIAS_CRYPTO("blake2s-160"); +-MODULE_ALIAS_CRYPTO("blake2s-160-x86"); +-MODULE_ALIAS_CRYPTO("blake2s-224"); +-MODULE_ALIAS_CRYPTO("blake2s-224-x86"); +-MODULE_ALIAS_CRYPTO("blake2s-256"); +-MODULE_ALIAS_CRYPTO("blake2s-256-x86"); +-MODULE_LICENSE("GPL v2"); +diff --git a/arch/x86/entry/Makefile b/arch/x86/entry/Makefile +index eeadbd7d92cc5..ca2fe186994b0 100644 +--- a/arch/x86/entry/Makefile ++++ b/arch/x86/entry/Makefile +@@ -11,12 +11,13 @@ CFLAGS_REMOVE_common.o = $(CC_FLAGS_FTRACE) + + CFLAGS_common.o += -fno-stack-protector + +-obj-y := entry.o entry_$(BITS).o thunk_$(BITS).o syscall_$(BITS).o ++obj-y := entry.o entry_$(BITS).o syscall_$(BITS).o + obj-y += common.o + + obj-y += vdso/ + obj-y += vsyscall/ + ++obj-$(CONFIG_PREEMPTION) += thunk_$(BITS).o + obj-$(CONFIG_IA32_EMULATION) += entry_64_compat.o syscall_32.o + obj-$(CONFIG_X86_X32_ABI) += syscall_x32.o + +diff --git a/arch/x86/entry/thunk_32.S b/arch/x86/entry/thunk_32.S +index 7591bab060f70..ff6e7003da974 100644 +--- a/arch/x86/entry/thunk_32.S ++++ b/arch/x86/entry/thunk_32.S +@@ -29,10 +29,8 @@ SYM_CODE_START_NOALIGN(\name) + SYM_CODE_END(\name) + .endm + +-#ifdef CONFIG_PREEMPTION + THUNK preempt_schedule_thunk, preempt_schedule + THUNK preempt_schedule_notrace_thunk, preempt_schedule_notrace + EXPORT_SYMBOL(preempt_schedule_thunk) + EXPORT_SYMBOL(preempt_schedule_notrace_thunk) +-#endif + +diff --git a/arch/x86/entry/thunk_64.S b/arch/x86/entry/thunk_64.S +index 505b488fcc655..f38b07d2768bb 100644 +--- a/arch/x86/entry/thunk_64.S ++++ b/arch/x86/entry/thunk_64.S +@@ -31,14 +31,11 @@ SYM_FUNC_END(\name) + _ASM_NOKPROBE(\name) + .endm + +-#ifdef CONFIG_PREEMPTION + THUNK preempt_schedule_thunk, preempt_schedule + THUNK preempt_schedule_notrace_thunk, preempt_schedule_notrace + EXPORT_SYMBOL(preempt_schedule_thunk) + EXPORT_SYMBOL(preempt_schedule_notrace_thunk) +-#endif + +-#ifdef CONFIG_PREEMPTION + SYM_CODE_START_LOCAL_NOALIGN(__thunk_restore) + popq %r11 + popq %r10 +@@ -53,4 +50,3 @@ SYM_CODE_START_LOCAL_NOALIGN(__thunk_restore) + RET + _ASM_NOKPROBE(__thunk_restore) + SYM_CODE_END(__thunk_restore) +-#endif +diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile +index c8891d3b38d30..c277c63195ce8 100644 +--- a/arch/x86/entry/vdso/Makefile ++++ b/arch/x86/entry/vdso/Makefile +@@ -179,7 +179,7 @@ quiet_cmd_vdso = VDSO $@ + sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@' + + VDSO_LDFLAGS = -shared --hash-style=both --build-id=sha1 \ +- $(call ld-option, --eh-frame-hdr) -Bsymbolic ++ $(call ld-option, --eh-frame-hdr) -Bsymbolic -z noexecstack + GCOV_PROFILE := n + + quiet_cmd_vdso_and_check = VDSO $@ +diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h +index a35f5e23fc2ac..74b5819120dab 100644 +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -498,6 +498,7 @@ struct kvm_pmu { + unsigned nr_arch_fixed_counters; + unsigned available_event_types; + u64 fixed_ctr_ctrl; ++ u64 fixed_ctr_ctrl_mask; + u64 global_ctrl; + u64 global_status; + u64 global_ovf_ctrl; +@@ -1562,7 +1563,7 @@ static inline int kvm_arch_flush_remote_tlb(struct kvm *kvm) + return -ENOTSUPP; + } + +-void kvm_mmu_x86_module_init(void); ++void __init kvm_mmu_x86_module_init(void); + int kvm_mmu_vendor_module_init(void); + void kvm_mmu_vendor_module_exit(void); + +diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c +index 837e617f3b76d..977d9d75e3add 100644 +--- a/arch/x86/kernel/cpu/bugs.c ++++ b/arch/x86/kernel/cpu/bugs.c +@@ -152,7 +152,7 @@ void __init check_bugs(void) + /* + * spectre_v2_user_select_mitigation() relies on the state set by + * retbleed_select_mitigation(); specifically the STIBP selection is +- * forced for UNRET. ++ * forced for UNRET or IBPB. + */ + spectre_v2_user_select_mitigation(); + ssb_select_mitigation(); +@@ -1172,7 +1172,8 @@ spectre_v2_user_select_mitigation(void) + boot_cpu_has(X86_FEATURE_AMD_STIBP_ALWAYS_ON)) + mode = SPECTRE_V2_USER_STRICT_PREFERRED; + +- if (retbleed_mitigation == RETBLEED_MITIGATION_UNRET) { ++ if (retbleed_mitigation == RETBLEED_MITIGATION_UNRET || ++ retbleed_mitigation == RETBLEED_MITIGATION_IBPB) { + if (mode != SPECTRE_V2_USER_STRICT && + mode != SPECTRE_V2_USER_STRICT_PREFERRED) + pr_info("Selecting STIBP always-on mode to complement retbleed mitigation\n"); +@@ -2353,10 +2354,11 @@ static ssize_t srbds_show_state(char *buf) + + static ssize_t retbleed_show_state(char *buf) + { +- if (retbleed_mitigation == RETBLEED_MITIGATION_UNRET) { ++ if (retbleed_mitigation == RETBLEED_MITIGATION_UNRET || ++ retbleed_mitigation == RETBLEED_MITIGATION_IBPB) { + if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD && + boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) +- return sprintf(buf, "Vulnerable: untrained return thunk on non-Zen uarch\n"); ++ return sprintf(buf, "Vulnerable: untrained return thunk / IBPB on non-AMD based uarch\n"); + + return sprintf(buf, "%s; SMT %s\n", + retbleed_strings[retbleed_mitigation], +diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c +index 2c87d62f191e2..ae7d4c85f4f43 100644 +--- a/arch/x86/kernel/cpu/intel.c ++++ b/arch/x86/kernel/cpu/intel.c +@@ -1145,22 +1145,23 @@ static void bus_lock_init(void) + { + u64 val; + +- /* +- * Warn and fatal are handled by #AC for split lock if #AC for +- * split lock is supported. +- */ +- if (!boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT) || +- (boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT) && +- (sld_state == sld_warn || sld_state == sld_fatal)) || +- sld_state == sld_off) ++ if (!boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT)) + return; + +- /* +- * Enable #DB for bus lock. All bus locks are handled in #DB except +- * split locks are handled in #AC in the fatal case. +- */ + rdmsrl(MSR_IA32_DEBUGCTLMSR, val); +- val |= DEBUGCTLMSR_BUS_LOCK_DETECT; ++ ++ if ((boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT) && ++ (sld_state == sld_warn || sld_state == sld_fatal)) || ++ sld_state == sld_off) { ++ /* ++ * Warn and fatal are handled by #AC for split lock if #AC for ++ * split lock is supported. ++ */ ++ val &= ~DEBUGCTLMSR_BUS_LOCK_DETECT; ++ } else { ++ val |= DEBUGCTLMSR_BUS_LOCK_DETECT; ++ } ++ + wrmsrl(MSR_IA32_DEBUGCTLMSR, val); + } + +diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c +index 74c2f88a43d0c..ceab282775461 100644 +--- a/arch/x86/kernel/ftrace.c ++++ b/arch/x86/kernel/ftrace.c +@@ -93,6 +93,7 @@ static int ftrace_verify_code(unsigned long ip, const char *old_code) + + /* Make sure it is what we expect it to be */ + if (memcmp(cur_code, old_code, MCOUNT_INSN_SIZE) != 0) { ++ ftrace_expected = old_code; + WARN_ON(1); + return -EINVAL; + } +diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c +index f6727c67ae028..7a7f671c60b4a 100644 +--- a/arch/x86/kernel/kprobes/core.c ++++ b/arch/x86/kernel/kprobes/core.c +@@ -816,16 +816,20 @@ NOKPROBE_SYMBOL(arch_prepare_kretprobe); + static void kprobe_post_process(struct kprobe *cur, struct pt_regs *regs, + struct kprobe_ctlblk *kcb) + { +- if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) { +- kcb->kprobe_status = KPROBE_HIT_SSDONE; +- cur->post_handler(cur, regs, 0); +- } +- + /* Restore back the original saved kprobes variables and continue. */ +- if (kcb->kprobe_status == KPROBE_REENTER) ++ if (kcb->kprobe_status == KPROBE_REENTER) { ++ /* This will restore both kcb and current_kprobe */ + restore_previous_kprobe(kcb); +- else ++ } else { ++ /* ++ * Always update the kcb status because ++ * reset_curent_kprobe() doesn't update kcb. ++ */ ++ kcb->kprobe_status = KPROBE_HIT_SSDONE; ++ if (cur->post_handler) ++ cur->post_handler(cur, regs, 0); + reset_current_kprobe(); ++ } + } + NOKPROBE_SYMBOL(kprobe_post_process); + +diff --git a/arch/x86/kernel/pmem.c b/arch/x86/kernel/pmem.c +index 6b07faaa15798..23154d24b1173 100644 +--- a/arch/x86/kernel/pmem.c ++++ b/arch/x86/kernel/pmem.c +@@ -27,6 +27,11 @@ static __init int register_e820_pmem(void) + * simply here to trigger the module to load on demand. + */ + pdev = platform_device_alloc("e820_pmem", -1); +- return platform_device_add(pdev); ++ ++ rc = platform_device_add(pdev); ++ if (rc) ++ platform_device_put(pdev); ++ ++ return rc; + } + device_initcall(register_e820_pmem); +diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c +index 8d9d72fc27a20..7073764535256 100644 +--- a/arch/x86/kernel/process.c ++++ b/arch/x86/kernel/process.c +@@ -805,6 +805,10 @@ static void amd_e400_idle(void) + */ + static int prefer_mwait_c1_over_halt(const struct cpuinfo_x86 *c) + { ++ /* User has disallowed the use of MWAIT. Fallback to HALT */ ++ if (boot_option_idle_override == IDLE_NOMWAIT) ++ return 0; ++ + if (c->x86_vendor != X86_VENDOR_INTEL) + return 0; + +@@ -913,9 +917,8 @@ static int __init idle_setup(char *str) + } else if (!strcmp(str, "nomwait")) { + /* + * If the boot option of "idle=nomwait" is added, +- * it means that mwait will be disabled for CPU C2/C3 +- * states. In such case it won't touch the variable +- * of boot_option_idle_override. ++ * it means that mwait will be disabled for CPU C1/C2/C3 ++ * states. + */ + boot_option_idle_override = IDLE_NOMWAIT; + } else +diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c +index 318a78379ca6c..8496ffc67c32d 100644 +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -1669,16 +1669,6 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt, + case VCPU_SREG_TR: + if (seg_desc.s || (seg_desc.type != 1 && seg_desc.type != 9)) + goto exception; +- if (!seg_desc.p) { +- err_vec = NP_VECTOR; +- goto exception; +- } +- old_desc = seg_desc; +- seg_desc.type |= 2; /* busy */ +- ret = ctxt->ops->cmpxchg_emulated(ctxt, desc_addr, &old_desc, &seg_desc, +- sizeof(seg_desc), &ctxt->exception); +- if (ret != X86EMUL_CONTINUE) +- return ret; + break; + case VCPU_SREG_LDTR: + if (seg_desc.s || seg_desc.type != 2) +@@ -1716,8 +1706,17 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt, + if (ret != X86EMUL_CONTINUE) + return ret; + if (emul_is_noncanonical_address(get_desc_base(&seg_desc) | +- ((u64)base3 << 32), ctxt)) +- return emulate_gp(ctxt, 0); ++ ((u64)base3 << 32), ctxt)) ++ return emulate_gp(ctxt, err_code); ++ } ++ ++ if (seg == VCPU_SREG_TR) { ++ old_desc = seg_desc; ++ seg_desc.type |= 2; /* busy */ ++ ret = ctxt->ops->cmpxchg_emulated(ctxt, desc_addr, &old_desc, &seg_desc, ++ sizeof(seg_desc), &ctxt->exception); ++ if (ret != X86EMUL_CONTINUE) ++ return ret; + } + load: + ctxt->ops->set_segment(ctxt, selector, &seg_desc, base3, seg); +diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c +index 3417405077adf..f267cca9fe094 100644 +--- a/arch/x86/kvm/mmu/mmu.c ++++ b/arch/x86/kvm/mmu/mmu.c +@@ -6115,7 +6115,7 @@ static int set_nx_huge_pages(const char *val, const struct kernel_param *kp) + * nx_huge_pages needs to be resolved to true/false when kvm.ko is loaded, as + * its default value of -1 is technically undefined behavior for a boolean. + */ +-void kvm_mmu_x86_module_init(void) ++void __init kvm_mmu_x86_module_init(void) + { + if (nx_huge_pages == -1) + __set_nx_huge_pages(get_nx_auto_mode()); +diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c +index 993daa6fb1287..78f1138753e65 100644 +--- a/arch/x86/kvm/svm/nested.c ++++ b/arch/x86/kvm/svm/nested.c +@@ -275,7 +275,8 @@ static bool nested_vmcb_check_cr3_cr4(struct kvm_vcpu *vcpu, + return false; + } + +- if (CC(!kvm_is_valid_cr4(vcpu, save->cr4))) ++ /* Note, SVM doesn't have any additional restrictions on CR4. */ ++ if (CC(!__kvm_is_valid_cr4(vcpu, save->cr4))) + return false; + + return true; +diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c +index 5b51156712f74..2947e3c965e32 100644 +--- a/arch/x86/kvm/svm/svm.c ++++ b/arch/x86/kvm/svm/svm.c +@@ -394,6 +394,10 @@ static void svm_queue_exception(struct kvm_vcpu *vcpu) + */ + (void)skip_emulated_instruction(vcpu); + rip = kvm_rip_read(vcpu); ++ ++ if (boot_cpu_has(X86_FEATURE_NRIPS)) ++ svm->vmcb->control.next_rip = rip; ++ + svm->int3_rip = rip + svm->vmcb->save.cs.base; + svm->int3_injected = rip - old_rip; + } +@@ -3417,8 +3421,6 @@ static void svm_set_irq(struct kvm_vcpu *vcpu) + { + struct vcpu_svm *svm = to_svm(vcpu); + +- BUG_ON(!(gif_set(svm))); +- + trace_kvm_inj_virq(vcpu->arch.interrupt.nr); + ++vcpu->stat.irq_injections; + +@@ -3682,6 +3684,18 @@ static void svm_complete_interrupts(struct kvm_vcpu *vcpu) + vector = exitintinfo & SVM_EXITINTINFO_VEC_MASK; + type = exitintinfo & SVM_EXITINTINFO_TYPE_MASK; + ++ /* ++ * If NextRIP isn't enabled, KVM must manually advance RIP prior to ++ * injecting the soft exception/interrupt. That advancement needs to ++ * be unwound if vectoring didn't complete. Note, the new event may ++ * not be the injected event, e.g. if KVM injected an INTn, the INTn ++ * hit a #NP in the guest, and the #NP encountered a #PF, the #NP will ++ * be the reported vectored event, but RIP still needs to be unwound. ++ */ ++ if (int3_injected && type == SVM_EXITINTINFO_TYPE_EXEPT && ++ kvm_is_linear_rip(vcpu, svm->int3_rip)) ++ kvm_rip_write(vcpu, kvm_rip_read(vcpu) - int3_injected); ++ + switch (type) { + case SVM_EXITINTINFO_TYPE_NMI: + vcpu->arch.nmi_injected = true; +@@ -3695,16 +3709,11 @@ static void svm_complete_interrupts(struct kvm_vcpu *vcpu) + + /* + * In case of software exceptions, do not reinject the vector, +- * but re-execute the instruction instead. Rewind RIP first +- * if we emulated INT3 before. ++ * but re-execute the instruction instead. + */ +- if (kvm_exception_is_soft(vector)) { +- if (vector == BP_VECTOR && int3_injected && +- kvm_is_linear_rip(vcpu, svm->int3_rip)) +- kvm_rip_write(vcpu, +- kvm_rip_read(vcpu) - int3_injected); ++ if (kvm_exception_is_soft(vector)) + break; +- } ++ + if (exitintinfo & SVM_EXITINTINFO_VALID_ERR) { + u32 err = svm->vmcb->control.exit_int_info_err; + kvm_requeue_exception_e(vcpu, vector, err); +diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c +index 5f91aa62bdca0..61d6013870581 100644 +--- a/arch/x86/kvm/vmx/nested.c ++++ b/arch/x86/kvm/vmx/nested.c +@@ -1217,7 +1217,7 @@ static int vmx_restore_vmx_basic(struct vcpu_vmx *vmx, u64 data) + BIT_ULL(49) | BIT_ULL(54) | BIT_ULL(55) | + /* reserved */ + BIT_ULL(31) | GENMASK_ULL(47, 45) | GENMASK_ULL(63, 56); +- u64 vmx_basic = vmx->nested.msrs.basic; ++ u64 vmx_basic = vmcs_config.nested.basic; + + if (!is_bitwise_subset(vmx_basic, data, feature_and_reserved)) + return -EINVAL; +@@ -1240,36 +1240,42 @@ static int vmx_restore_vmx_basic(struct vcpu_vmx *vmx, u64 data) + return 0; + } + +-static int +-vmx_restore_control_msr(struct vcpu_vmx *vmx, u32 msr_index, u64 data) ++static void vmx_get_control_msr(struct nested_vmx_msrs *msrs, u32 msr_index, ++ u32 **low, u32 **high) + { +- u64 supported; +- u32 *lowp, *highp; +- + switch (msr_index) { + case MSR_IA32_VMX_TRUE_PINBASED_CTLS: +- lowp = &vmx->nested.msrs.pinbased_ctls_low; +- highp = &vmx->nested.msrs.pinbased_ctls_high; ++ *low = &msrs->pinbased_ctls_low; ++ *high = &msrs->pinbased_ctls_high; + break; + case MSR_IA32_VMX_TRUE_PROCBASED_CTLS: +- lowp = &vmx->nested.msrs.procbased_ctls_low; +- highp = &vmx->nested.msrs.procbased_ctls_high; ++ *low = &msrs->procbased_ctls_low; ++ *high = &msrs->procbased_ctls_high; + break; + case MSR_IA32_VMX_TRUE_EXIT_CTLS: +- lowp = &vmx->nested.msrs.exit_ctls_low; +- highp = &vmx->nested.msrs.exit_ctls_high; ++ *low = &msrs->exit_ctls_low; ++ *high = &msrs->exit_ctls_high; + break; + case MSR_IA32_VMX_TRUE_ENTRY_CTLS: +- lowp = &vmx->nested.msrs.entry_ctls_low; +- highp = &vmx->nested.msrs.entry_ctls_high; ++ *low = &msrs->entry_ctls_low; ++ *high = &msrs->entry_ctls_high; + break; + case MSR_IA32_VMX_PROCBASED_CTLS2: +- lowp = &vmx->nested.msrs.secondary_ctls_low; +- highp = &vmx->nested.msrs.secondary_ctls_high; ++ *low = &msrs->secondary_ctls_low; ++ *high = &msrs->secondary_ctls_high; + break; + default: + BUG(); + } ++} ++ ++static int ++vmx_restore_control_msr(struct vcpu_vmx *vmx, u32 msr_index, u64 data) ++{ ++ u32 *lowp, *highp; ++ u64 supported; ++ ++ vmx_get_control_msr(&vmcs_config.nested, msr_index, &lowp, &highp); + + supported = vmx_control_msr(*lowp, *highp); + +@@ -1281,6 +1287,7 @@ vmx_restore_control_msr(struct vcpu_vmx *vmx, u32 msr_index, u64 data) + if (!is_bitwise_subset(supported, data, GENMASK_ULL(63, 32))) + return -EINVAL; + ++ vmx_get_control_msr(&vmx->nested.msrs, msr_index, &lowp, &highp); + *lowp = data; + *highp = data >> 32; + return 0; +@@ -1294,10 +1301,8 @@ static int vmx_restore_vmx_misc(struct vcpu_vmx *vmx, u64 data) + BIT_ULL(28) | BIT_ULL(29) | BIT_ULL(30) | + /* reserved */ + GENMASK_ULL(13, 9) | BIT_ULL(31); +- u64 vmx_misc; +- +- vmx_misc = vmx_control_msr(vmx->nested.msrs.misc_low, +- vmx->nested.msrs.misc_high); ++ u64 vmx_misc = vmx_control_msr(vmcs_config.nested.misc_low, ++ vmcs_config.nested.misc_high); + + if (!is_bitwise_subset(vmx_misc, data, feature_and_reserved_bits)) + return -EINVAL; +@@ -1325,10 +1330,8 @@ static int vmx_restore_vmx_misc(struct vcpu_vmx *vmx, u64 data) + + static int vmx_restore_vmx_ept_vpid_cap(struct vcpu_vmx *vmx, u64 data) + { +- u64 vmx_ept_vpid_cap; +- +- vmx_ept_vpid_cap = vmx_control_msr(vmx->nested.msrs.ept_caps, +- vmx->nested.msrs.vpid_caps); ++ u64 vmx_ept_vpid_cap = vmx_control_msr(vmcs_config.nested.ept_caps, ++ vmcs_config.nested.vpid_caps); + + /* Every bit is either reserved or a feature bit. */ + if (!is_bitwise_subset(vmx_ept_vpid_cap, data, -1ULL)) +@@ -1339,20 +1342,21 @@ static int vmx_restore_vmx_ept_vpid_cap(struct vcpu_vmx *vmx, u64 data) + return 0; + } + +-static int vmx_restore_fixed0_msr(struct vcpu_vmx *vmx, u32 msr_index, u64 data) ++static u64 *vmx_get_fixed0_msr(struct nested_vmx_msrs *msrs, u32 msr_index) + { +- u64 *msr; +- + switch (msr_index) { + case MSR_IA32_VMX_CR0_FIXED0: +- msr = &vmx->nested.msrs.cr0_fixed0; +- break; ++ return &msrs->cr0_fixed0; + case MSR_IA32_VMX_CR4_FIXED0: +- msr = &vmx->nested.msrs.cr4_fixed0; +- break; ++ return &msrs->cr4_fixed0; + default: + BUG(); + } ++} ++ ++static int vmx_restore_fixed0_msr(struct vcpu_vmx *vmx, u32 msr_index, u64 data) ++{ ++ const u64 *msr = vmx_get_fixed0_msr(&vmcs_config.nested, msr_index); + + /* + * 1 bits (which indicates bits which "must-be-1" during VMX operation) +@@ -1361,7 +1365,7 @@ static int vmx_restore_fixed0_msr(struct vcpu_vmx *vmx, u32 msr_index, u64 data) + if (!is_bitwise_subset(data, *msr, -1ULL)) + return -EINVAL; + +- *msr = data; ++ *vmx_get_fixed0_msr(&vmx->nested.msrs, msr_index) = data; + return 0; + } + +@@ -1422,7 +1426,7 @@ int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) + vmx->nested.msrs.vmcs_enum = data; + return 0; + case MSR_IA32_VMX_VMFUNC: +- if (data & ~vmx->nested.msrs.vmfunc_controls) ++ if (data & ~vmcs_config.nested.vmfunc_controls) + return -EINVAL; + vmx->nested.msrs.vmfunc_controls = data; + return 0; +@@ -2269,7 +2273,6 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct loaded_vmcs *vmcs0 + SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | + SECONDARY_EXEC_APIC_REGISTER_VIRT | + SECONDARY_EXEC_ENABLE_VMFUNC | +- SECONDARY_EXEC_TSC_SCALING | + SECONDARY_EXEC_DESC); + + if (nested_cpu_has(vmcs12, +@@ -2608,6 +2611,7 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, + vcpu->arch.walk_mmu->inject_page_fault = vmx_inject_page_fault_nested; + + if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) && ++ intel_pmu_has_perf_global_ctrl(vcpu_to_pmu(vcpu)) && + WARN_ON_ONCE(kvm_set_msr(vcpu, MSR_CORE_PERF_GLOBAL_CTRL, + vmcs12->guest_ia32_perf_global_ctrl))) { + *entry_failure_code = ENTRY_FAIL_DEFAULT; +@@ -3364,10 +3368,12 @@ enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, + if (likely(!evaluate_pending_interrupts) && kvm_vcpu_apicv_active(vcpu)) + evaluate_pending_interrupts |= vmx_has_apicv_interrupt(vcpu); + +- if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS)) ++ if (!vmx->nested.nested_run_pending || ++ !(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS)) + vmx->nested.vmcs01_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL); + if (kvm_mpx_supported() && +- !(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS)) ++ (!vmx->nested.nested_run_pending || ++ !(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS))) + vmx->nested.vmcs01_guest_bndcfgs = vmcs_read64(GUEST_BNDCFGS); + + /* +@@ -4324,7 +4330,8 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu, + vmcs_write64(GUEST_IA32_PAT, vmcs12->host_ia32_pat); + vcpu->arch.pat = vmcs12->host_ia32_pat; + } +- if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL) ++ if ((vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL) && ++ intel_pmu_has_perf_global_ctrl(vcpu_to_pmu(vcpu))) + WARN_ON_ONCE(kvm_set_msr(vcpu, MSR_CORE_PERF_GLOBAL_CTRL, + vmcs12->host_ia32_perf_global_ctrl)); + +@@ -4946,20 +4953,25 @@ static int handle_vmon(struct kvm_vcpu *vcpu) + | FEAT_CTL_VMX_ENABLED_OUTSIDE_SMX; + + /* +- * The Intel VMX Instruction Reference lists a bunch of bits that are +- * prerequisite to running VMXON, most notably cr4.VMXE must be set to +- * 1 (see vmx_is_valid_cr4() for when we allow the guest to set this). +- * Otherwise, we should fail with #UD. But most faulting conditions +- * have already been checked by hardware, prior to the VM-exit for +- * VMXON. We do test guest cr4.VMXE because processor CR4 always has +- * that bit set to 1 in non-root mode. ++ * Note, KVM cannot rely on hardware to perform the CR0/CR4 #UD checks ++ * that have higher priority than VM-Exit (see Intel SDM's pseudocode ++ * for VMXON), as KVM must load valid CR0/CR4 values into hardware while ++ * running the guest, i.e. KVM needs to check the _guest_ values. ++ * ++ * Rely on hardware for the other two pre-VM-Exit checks, !VM86 and ++ * !COMPATIBILITY modes. KVM may run the guest in VM86 to emulate Real ++ * Mode, but KVM will never take the guest out of those modes. + */ +- if (!kvm_read_cr4_bits(vcpu, X86_CR4_VMXE)) { ++ if (!nested_host_cr0_valid(vcpu, kvm_read_cr0(vcpu)) || ++ !nested_host_cr4_valid(vcpu, kvm_read_cr4(vcpu))) { + kvm_queue_exception(vcpu, UD_VECTOR); + return 1; + } + +- /* CPL=0 must be checked manually. */ ++ /* ++ * CPL=0 and all other checks that are lower priority than VM-Exit must ++ * be checked manually. ++ */ + if (vmx_get_cpl(vcpu)) { + kvm_inject_gp(vcpu, 0); + return 1; +@@ -6726,6 +6738,9 @@ void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps) + rdmsrl(MSR_IA32_VMX_CR0_FIXED1, msrs->cr0_fixed1); + rdmsrl(MSR_IA32_VMX_CR4_FIXED1, msrs->cr4_fixed1); + ++ if (vmx_umip_emulated()) ++ msrs->cr4_fixed1 |= X86_CR4_UMIP; ++ + msrs->vmcs_enum = nested_vmx_calc_vmcs_enum_msr(); + } + +diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h +index b69a80f43b37e..2d0ac8a86d4a4 100644 +--- a/arch/x86/kvm/vmx/nested.h ++++ b/arch/x86/kvm/vmx/nested.h +@@ -280,7 +280,8 @@ static inline bool nested_cr4_valid(struct kvm_vcpu *vcpu, unsigned long val) + u64 fixed0 = to_vmx(vcpu)->nested.msrs.cr4_fixed0; + u64 fixed1 = to_vmx(vcpu)->nested.msrs.cr4_fixed1; + +- return fixed_bits_valid(val, fixed0, fixed1); ++ return fixed_bits_valid(val, fixed0, fixed1) && ++ __kvm_is_valid_cr4(vcpu, val); + } + + /* No difference in the restrictions on guest and host CR4 in VMX operation. */ +diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c +index e7275ce15a8b0..e624a39365ecb 100644 +--- a/arch/x86/kvm/vmx/pmu_intel.c ++++ b/arch/x86/kvm/vmx/pmu_intel.c +@@ -104,6 +104,9 @@ static bool intel_pmc_is_enabled(struct kvm_pmc *pmc) + { + struct kvm_pmu *pmu = pmc_to_pmu(pmc); + ++ if (!intel_pmu_has_perf_global_ctrl(pmu)) ++ return true; ++ + return test_bit(pmc->idx, (unsigned long *)&pmu->global_ctrl); + } + +@@ -219,7 +222,7 @@ static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr) + case MSR_CORE_PERF_GLOBAL_STATUS: + case MSR_CORE_PERF_GLOBAL_CTRL: + case MSR_CORE_PERF_GLOBAL_OVF_CTRL: +- ret = pmu->version > 1; ++ return intel_pmu_has_perf_global_ctrl(pmu); + break; + default: + ret = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0) || +@@ -402,7 +405,7 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) + case MSR_CORE_PERF_FIXED_CTR_CTRL: + if (pmu->fixed_ctr_ctrl == data) + return 0; +- if (!(data & 0xfffffffffffff444ull)) { ++ if (!(data & pmu->fixed_ctr_ctrl_mask)) { + reprogram_fixed_counters(pmu, data); + return 0; + } +@@ -472,6 +475,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) + struct kvm_cpuid_entry2 *entry; + union cpuid10_eax eax; + union cpuid10_edx edx; ++ int i; + + pmu->nr_arch_gp_counters = 0; + pmu->nr_arch_fixed_counters = 0; +@@ -480,6 +484,9 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) + pmu->version = 0; + pmu->reserved_bits = 0xffffffff00200000ull; + pmu->raw_event_mask = X86_RAW_EVENT_MASK; ++ pmu->global_ctrl_mask = ~0ull; ++ pmu->global_ovf_ctrl_mask = ~0ull; ++ pmu->fixed_ctr_ctrl_mask = ~0ull; + + entry = kvm_find_cpuid_entry(vcpu, 0xa, 0); + if (!entry) +@@ -513,6 +520,8 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) + ((u64)1 << edx.split.bit_width_fixed) - 1; + } + ++ for (i = 0; i < pmu->nr_arch_fixed_counters; i++) ++ pmu->fixed_ctr_ctrl_mask &= ~(0xbull << (i * 4)); + pmu->global_ctrl = ((1ull << pmu->nr_arch_gp_counters) - 1) | + (((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED); + pmu->global_ctrl_mask = ~pmu->global_ctrl; +diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c +index 359292767e177..cfb3a5c809f2e 100644 +--- a/arch/x86/kvm/vmx/vmx.c ++++ b/arch/x86/kvm/vmx/vmx.c +@@ -3213,8 +3213,8 @@ static bool vmx_is_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) + { + /* + * We operate under the default treatment of SMM, so VMX cannot be +- * enabled under SMM. Note, whether or not VMXE is allowed at all is +- * handled by kvm_is_valid_cr4(). ++ * enabled under SMM. Note, whether or not VMXE is allowed at all, ++ * i.e. is a reserved bit, is handled by common x86 code. + */ + if ((cr4 & X86_CR4_VMXE) && is_smm(vcpu)) + return false; +diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h +index a8b8150252bb7..20f1213a93685 100644 +--- a/arch/x86/kvm/vmx/vmx.h ++++ b/arch/x86/kvm/vmx/vmx.h +@@ -92,6 +92,18 @@ union vmx_exit_reason { + u32 full; + }; + ++static inline bool intel_pmu_has_perf_global_ctrl(struct kvm_pmu *pmu) ++{ ++ /* ++ * Architecturally, Intel's SDM states that IA32_PERF_GLOBAL_CTRL is ++ * supported if "CPUID.0AH: EAX[7:0] > 0", i.e. if the PMU version is ++ * greater than zero. However, KVM only exposes and emulates the MSR ++ * to/for the guest if the guest PMU supports at least "Architectural ++ * Performance Monitoring Version 2". ++ */ ++ return pmu->version > 1; ++} ++ + #define vcpu_to_lbr_desc(vcpu) (&to_vmx(vcpu)->lbr_desc) + #define vcpu_to_lbr_records(vcpu) (&to_vmx(vcpu)->lbr_desc.records) + +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 8a6ee5d8adc74..f5b7a05530eb0 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -1031,7 +1031,7 @@ int kvm_emulate_xsetbv(struct kvm_vcpu *vcpu) + } + EXPORT_SYMBOL_GPL(kvm_emulate_xsetbv); + +-bool kvm_is_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) ++bool __kvm_is_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) + { + if (cr4 & cr4_reserved_bits) + return false; +@@ -1039,9 +1039,15 @@ bool kvm_is_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) + if (cr4 & vcpu->arch.cr4_guest_rsvd_bits) + return false; + +- return static_call(kvm_x86_is_valid_cr4)(vcpu, cr4); ++ return true; ++} ++EXPORT_SYMBOL_GPL(__kvm_is_valid_cr4); ++ ++static bool kvm_is_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) ++{ ++ return __kvm_is_valid_cr4(vcpu, cr4) && ++ static_call(kvm_x86_is_valid_cr4)(vcpu, cr4); + } +-EXPORT_SYMBOL_GPL(kvm_is_valid_cr4); + + void kvm_post_set_cr4(struct kvm_vcpu *vcpu, unsigned long old_cr4, unsigned long cr4) + { +@@ -3096,17 +3102,20 @@ static int set_msr_mce(struct kvm_vcpu *vcpu, struct msr_data *msr_info) + /* only 0 or all 1s can be written to IA32_MCi_CTL + * some Linux kernels though clear bit 10 in bank 4 to + * workaround a BIOS/GART TBL issue on AMD K8s, ignore +- * this to avoid an uncatched #GP in the guest ++ * this to avoid an uncatched #GP in the guest. ++ * ++ * UNIXWARE clears bit 0 of MC1_CTL to ignore ++ * correctable, single-bit ECC data errors. + */ + if ((offset & 0x3) == 0 && +- data != 0 && (data | (1 << 10)) != ~(u64)0) +- return -1; ++ data != 0 && (data | (1 << 10) | 1) != ~(u64)0) ++ return 1; + + /* MCi_STATUS */ + if (!msr_info->host_initiated && + (offset & 0x3) == 1 && data != 0) { + if (!can_set_mci_status(vcpu)) +- return -1; ++ return 1; + } + + vcpu->arch.mce_banks[offset] = data; +@@ -3238,6 +3247,7 @@ static void record_steal_time(struct kvm_vcpu *vcpu) + struct gfn_to_hva_cache *ghc = &vcpu->arch.st.cache; + struct kvm_steal_time __user *st; + struct kvm_memslots *slots; ++ gpa_t gpa = vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS; + u64 steal; + u32 version; + +@@ -3255,13 +3265,12 @@ static void record_steal_time(struct kvm_vcpu *vcpu) + slots = kvm_memslots(vcpu->kvm); + + if (unlikely(slots->generation != ghc->generation || ++ gpa != ghc->gpa || + kvm_is_error_hva(ghc->hva) || !ghc->memslot)) { +- gfn_t gfn = vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS; +- + /* We rely on the fact that it fits in a single page. */ + BUILD_BUG_ON((sizeof(*st) - 1) & KVM_STEAL_VALID_BITS); + +- if (kvm_gfn_to_hva_cache_init(vcpu->kvm, ghc, gfn, sizeof(*st)) || ++ if (kvm_gfn_to_hva_cache_init(vcpu->kvm, ghc, gpa, sizeof(*st)) || + kvm_is_error_hva(ghc->hva) || !ghc->memslot) + return; + } +@@ -4372,6 +4381,7 @@ static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu) + struct kvm_steal_time __user *st; + struct kvm_memslots *slots; + static const u8 preempted = KVM_VCPU_PREEMPTED; ++ gpa_t gpa = vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS; + + /* + * The vCPU can be marked preempted if and only if the VM-Exit was on +@@ -4399,6 +4409,7 @@ static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu) + slots = kvm_memslots(vcpu->kvm); + + if (unlikely(slots->generation != ghc->generation || ++ gpa != ghc->gpa || + kvm_is_error_hva(ghc->hva) || !ghc->memslot)) + return; + +diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h +index bc7ef6820ac8f..4d6f7a70bdd14 100644 +--- a/arch/x86/kvm/x86.h ++++ b/arch/x86/kvm/x86.h +@@ -448,7 +448,7 @@ static inline void kvm_machine_check(void) + void kvm_load_guest_xsave_state(struct kvm_vcpu *vcpu); + void kvm_load_host_xsave_state(struct kvm_vcpu *vcpu); + int kvm_spec_ctrl_test_value(u64 value); +-bool kvm_is_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4); ++bool __kvm_is_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4); + int kvm_handle_memory_failure(struct kvm_vcpu *vcpu, int r, + struct x86_exception *e); + int kvm_handle_invpcid(struct kvm_vcpu *vcpu, unsigned long type, gva_t gva); +diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c +index 13d838e6030bc..a9c7efd4b7946 100644 +--- a/arch/x86/mm/extable.c ++++ b/arch/x86/mm/extable.c +@@ -86,16 +86,18 @@ static bool ex_handler_copy(const struct exception_table_entry *fixup, + static bool ex_handler_msr(const struct exception_table_entry *fixup, + struct pt_regs *regs, bool wrmsr, bool safe, int reg) + { +- if (!safe && wrmsr && +- pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", +- (unsigned int)regs->cx, (unsigned int)regs->dx, +- (unsigned int)regs->ax, regs->ip, (void *)regs->ip)) ++ if (__ONCE_LITE_IF(!safe && wrmsr)) { ++ pr_warn("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", ++ (unsigned int)regs->cx, (unsigned int)regs->dx, ++ (unsigned int)regs->ax, regs->ip, (void *)regs->ip); + show_stack_regs(regs); ++ } + +- if (!safe && !wrmsr && +- pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", +- (unsigned int)regs->cx, regs->ip, (void *)regs->ip)) ++ if (__ONCE_LITE_IF(!safe && !wrmsr)) { ++ pr_warn("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", ++ (unsigned int)regs->cx, regs->ip, (void *)regs->ip); + show_stack_regs(regs); ++ } + + if (!wrmsr) { + /* Pretend that the read succeeded and returned 0. */ +diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c +index 1e9b93b088dbf..e360c6892a584 100644 +--- a/arch/x86/mm/numa.c ++++ b/arch/x86/mm/numa.c +@@ -860,7 +860,7 @@ void debug_cpumask_set_cpu(int cpu, int node, bool enable) + return; + } + mask = node_to_cpumask_map[node]; +- if (!mask) { ++ if (!cpumask_available(mask)) { + pr_err("node_to_cpumask_map[%i] NULL\n", node); + dump_stack(); + return; +@@ -906,7 +906,7 @@ const struct cpumask *cpumask_of_node(int node) + dump_stack(); + return cpu_none_mask; + } +- if (node_to_cpumask_map[node] == NULL) { ++ if (!cpumask_available(node_to_cpumask_map[node])) { + printk(KERN_WARNING + "cpumask_of_node(%d): no node_to_cpumask_map!\n", + node); +diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c +index f03a6883dcc6d..89f25af4b3c33 100644 +--- a/arch/x86/platform/olpc/olpc-xo1-sci.c ++++ b/arch/x86/platform/olpc/olpc-xo1-sci.c +@@ -80,7 +80,7 @@ static void send_ebook_state(void) + return; + } + +- if (!!test_bit(SW_TABLET_MODE, ebook_switch_idev->sw) == state) ++ if (test_bit(SW_TABLET_MODE, ebook_switch_idev->sw) == !!state) + return; /* Nothing new to report. */ + + input_report_switch(ebook_switch_idev, SW_TABLET_MODE, state); +diff --git a/arch/x86/um/Makefile b/arch/x86/um/Makefile +index 5ccb18290d717..a8591ec8ae682 100644 +--- a/arch/x86/um/Makefile ++++ b/arch/x86/um/Makefile +@@ -28,7 +28,8 @@ else + + obj-y += syscalls_64.o vdso/ + +-subarch-y = ../lib/csum-partial_64.o ../lib/memcpy_64.o ../entry/thunk_64.o ++subarch-y = ../lib/csum-partial_64.o ../lib/memcpy_64.o ++subarch-$(CONFIG_PREEMPTION) += ../entry/thunk_64.o + + endif + +diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c +index 4986226a5ab26..08d70c868c130 100644 +--- a/arch/xtensa/platforms/iss/network.c ++++ b/arch/xtensa/platforms/iss/network.c +@@ -502,16 +502,24 @@ static const struct net_device_ops iss_netdev_ops = { + .ndo_set_rx_mode = iss_net_set_multicast_list, + }; + +-static int iss_net_configure(int index, char *init) ++static void iss_net_pdev_release(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct iss_net_private *lp = ++ container_of(pdev, struct iss_net_private, pdev); ++ ++ free_netdev(lp->dev); ++} ++ ++static void iss_net_configure(int index, char *init) + { + struct net_device *dev; + struct iss_net_private *lp; +- int err; + + dev = alloc_etherdev(sizeof(*lp)); + if (dev == NULL) { + pr_err("eth_configure: failed to allocate device\n"); +- return 1; ++ return; + } + + /* Initialize private element. */ +@@ -540,7 +548,7 @@ static int iss_net_configure(int index, char *init) + if (!tuntap_probe(lp, index, init)) { + pr_err("%s: invalid arguments. Skipping device!\n", + dev->name); +- goto errout; ++ goto err_free_netdev; + } + + pr_info("Netdevice %d (%pM)\n", index, dev->dev_addr); +@@ -548,7 +556,8 @@ static int iss_net_configure(int index, char *init) + /* sysfs register */ + + if (!driver_registered) { +- platform_driver_register(&iss_net_driver); ++ if (platform_driver_register(&iss_net_driver)) ++ goto err_free_netdev; + driver_registered = 1; + } + +@@ -558,7 +567,9 @@ static int iss_net_configure(int index, char *init) + + lp->pdev.id = index; + lp->pdev.name = DRIVER_NAME; +- platform_device_register(&lp->pdev); ++ lp->pdev.dev.release = iss_net_pdev_release; ++ if (platform_device_register(&lp->pdev)) ++ goto err_free_netdev; + SET_NETDEV_DEV(dev, &lp->pdev.dev); + + dev->netdev_ops = &iss_netdev_ops; +@@ -567,23 +578,20 @@ static int iss_net_configure(int index, char *init) + dev->irq = -1; + + rtnl_lock(); +- err = register_netdevice(dev); +- rtnl_unlock(); +- +- if (err) { ++ if (register_netdevice(dev)) { ++ rtnl_unlock(); + pr_err("%s: error registering net device!\n", dev->name); +- /* XXX: should we call ->remove() here? */ +- free_netdev(dev); +- return 1; ++ platform_device_unregister(&lp->pdev); ++ return; + } ++ rtnl_unlock(); + + timer_setup(&lp->tl, iss_net_user_timer_expire, 0); + +- return 0; ++ return; + +-errout: +- /* FIXME: unregister; free, etc.. */ +- return -EIO; ++err_free_netdev: ++ free_netdev(dev); + } + + /* ------------------------------------------------------------------------- */ +diff --git a/block/bio.c b/block/bio.c +index b8a8bfba714f4..ba9120d4fe499 100644 +--- a/block/bio.c ++++ b/block/bio.c +@@ -1071,6 +1071,37 @@ static void bio_put_pages(struct page **pages, size_t size, size_t off) + put_page(pages[i]); + } + ++static int bio_iov_add_page(struct bio *bio, struct page *page, ++ unsigned int len, unsigned int offset) ++{ ++ bool same_page = false; ++ ++ if (!__bio_try_merge_page(bio, page, len, offset, &same_page)) { ++ if (WARN_ON_ONCE(bio_full(bio, len))) ++ return -EINVAL; ++ __bio_add_page(bio, page, len, offset); ++ return 0; ++ } ++ ++ if (same_page) ++ put_page(page); ++ return 0; ++} ++ ++static int bio_iov_add_zone_append_page(struct bio *bio, struct page *page, ++ unsigned int len, unsigned int offset) ++{ ++ struct request_queue *q = bdev_get_queue(bio->bi_bdev); ++ bool same_page = false; ++ ++ if (bio_add_hw_page(q, bio, page, len, offset, ++ queue_max_zone_append_sectors(q), &same_page) != len) ++ return -EINVAL; ++ if (same_page) ++ put_page(page); ++ return 0; ++} ++ + #define PAGE_PTRS_PER_BVEC (sizeof(struct bio_vec) / sizeof(struct page *)) + + /** +@@ -1089,61 +1120,11 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter) + unsigned short entries_left = bio->bi_max_vecs - bio->bi_vcnt; + struct bio_vec *bv = bio->bi_io_vec + bio->bi_vcnt; + struct page **pages = (struct page **)bv; +- bool same_page = false; +- ssize_t size, left; +- unsigned len, i; +- size_t offset; +- +- /* +- * Move page array up in the allocated memory for the bio vecs as far as +- * possible so that we can start filling biovecs from the beginning +- * without overwriting the temporary page array. +- */ +- BUILD_BUG_ON(PAGE_PTRS_PER_BVEC < 2); +- pages += entries_left * (PAGE_PTRS_PER_BVEC - 1); +- +- size = iov_iter_get_pages(iter, pages, LONG_MAX, nr_pages, &offset); +- if (unlikely(size <= 0)) +- return size ? size : -EFAULT; +- +- for (left = size, i = 0; left > 0; left -= len, i++) { +- struct page *page = pages[i]; +- +- len = min_t(size_t, PAGE_SIZE - offset, left); +- +- if (__bio_try_merge_page(bio, page, len, offset, &same_page)) { +- if (same_page) +- put_page(page); +- } else { +- if (WARN_ON_ONCE(bio_full(bio, len))) { +- bio_put_pages(pages + i, left, offset); +- return -EINVAL; +- } +- __bio_add_page(bio, page, len, offset); +- } +- offset = 0; +- } +- +- iov_iter_advance(iter, size); +- return 0; +-} +- +-static int __bio_iov_append_get_pages(struct bio *bio, struct iov_iter *iter) +-{ +- unsigned short nr_pages = bio->bi_max_vecs - bio->bi_vcnt; +- unsigned short entries_left = bio->bi_max_vecs - bio->bi_vcnt; +- struct request_queue *q = bdev_get_queue(bio->bi_bdev); +- unsigned int max_append_sectors = queue_max_zone_append_sectors(q); +- struct bio_vec *bv = bio->bi_io_vec + bio->bi_vcnt; +- struct page **pages = (struct page **)bv; + ssize_t size, left; + unsigned len, i; + size_t offset; + int ret = 0; + +- if (WARN_ON_ONCE(!max_append_sectors)) +- return 0; +- + /* + * Move page array up in the allocated memory for the bio vecs as far as + * possible so that we can start filling biovecs from the beginning +@@ -1158,17 +1139,18 @@ static int __bio_iov_append_get_pages(struct bio *bio, struct iov_iter *iter) + + for (left = size, i = 0; left > 0; left -= len, i++) { + struct page *page = pages[i]; +- bool same_page = false; + + len = min_t(size_t, PAGE_SIZE - offset, left); +- if (bio_add_hw_page(q, bio, page, len, offset, +- max_append_sectors, &same_page) != len) { ++ if (bio_op(bio) == REQ_OP_ZONE_APPEND) ++ ret = bio_iov_add_zone_append_page(bio, page, len, ++ offset); ++ else ++ ret = bio_iov_add_page(bio, page, len, offset); ++ ++ if (ret) { + bio_put_pages(pages + i, left, offset); +- ret = -EINVAL; + break; + } +- if (same_page) +- put_page(page); + offset = 0; + } + +@@ -1210,10 +1192,7 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter) + } + + do { +- if (bio_op(bio) == REQ_OP_ZONE_APPEND) +- ret = __bio_iov_append_get_pages(bio, iter); +- else +- ret = __bio_iov_iter_get_pages(bio, iter); ++ ret = __bio_iov_iter_get_pages(bio, iter); + } while (!ret && iov_iter_count(iter) && !bio_full(bio, 0)); + + /* don't account direct I/O as memory stall */ +diff --git a/block/blk-iocost.c b/block/blk-iocost.c +index 10851493940c3..069193dee95b0 100644 +--- a/block/blk-iocost.c ++++ b/block/blk-iocost.c +@@ -2893,15 +2893,21 @@ static int blk_iocost_init(struct request_queue *q) + * called before policy activation completion, can't assume that the + * target bio has an iocg associated and need to test for NULL iocg. + */ +- rq_qos_add(q, rqos); ++ ret = rq_qos_add(q, rqos); ++ if (ret) ++ goto err_free_ioc; ++ + ret = blkcg_activate_policy(q, &blkcg_policy_iocost); +- if (ret) { +- rq_qos_del(q, rqos); +- free_percpu(ioc->pcpu_stat); +- kfree(ioc); +- return ret; +- } ++ if (ret) ++ goto err_del_qos; + return 0; ++ ++err_del_qos: ++ rq_qos_del(q, rqos); ++err_free_ioc: ++ free_percpu(ioc->pcpu_stat); ++ kfree(ioc); ++ return ret; + } + + static struct blkcg_policy_data *ioc_cpd_alloc(gfp_t gfp) +diff --git a/block/blk-iolatency.c b/block/blk-iolatency.c +index d85f30a85ee75..bdef8395af6e7 100644 +--- a/block/blk-iolatency.c ++++ b/block/blk-iolatency.c +@@ -772,19 +772,23 @@ int blk_iolatency_init(struct request_queue *q) + rqos->ops = &blkcg_iolatency_ops; + rqos->q = q; + +- rq_qos_add(q, rqos); +- ++ ret = rq_qos_add(q, rqos); ++ if (ret) ++ goto err_free; + ret = blkcg_activate_policy(q, &blkcg_policy_iolatency); +- if (ret) { +- rq_qos_del(q, rqos); +- kfree(blkiolat); +- return ret; +- } ++ if (ret) ++ goto err_qos_del; + + timer_setup(&blkiolat->timer, blkiolatency_timer_fn, 0); + INIT_WORK(&blkiolat->enable_work, blkiolatency_enable_work_fn); + + return 0; ++ ++err_qos_del: ++ rq_qos_del(q, rqos); ++err_free: ++ kfree(blkiolat); ++ return ret; + } + + static void iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val) +diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c +index 3b38d15723de1..7023257a133df 100644 +--- a/block/blk-mq-debugfs.c ++++ b/block/blk-mq-debugfs.c +@@ -879,6 +879,9 @@ void blk_mq_debugfs_register_hctx(struct request_queue *q, + char name[20]; + int i; + ++ if (!q->debugfs_dir) ++ return; ++ + snprintf(name, sizeof(name), "hctx%u", hctx->queue_num); + hctx->debugfs_dir = debugfs_create_dir(name, q->debugfs_dir); + +diff --git a/block/blk-rq-qos.h b/block/blk-rq-qos.h +index 68267007da1c6..1655f76b6a1b6 100644 +--- a/block/blk-rq-qos.h ++++ b/block/blk-rq-qos.h +@@ -86,7 +86,7 @@ static inline void rq_wait_init(struct rq_wait *rq_wait) + init_waitqueue_head(&rq_wait->wait); + } + +-static inline void rq_qos_add(struct request_queue *q, struct rq_qos *rqos) ++static inline int rq_qos_add(struct request_queue *q, struct rq_qos *rqos) + { + /* + * No IO can be in-flight when adding rqos, so freeze queue, which +@@ -98,6 +98,8 @@ static inline void rq_qos_add(struct request_queue *q, struct rq_qos *rqos) + blk_mq_freeze_queue(q); + + spin_lock_irq(&q->queue_lock); ++ if (rq_qos_id(q, rqos->id)) ++ goto ebusy; + rqos->next = q->rq_qos; + q->rq_qos = rqos; + spin_unlock_irq(&q->queue_lock); +@@ -106,6 +108,13 @@ static inline void rq_qos_add(struct request_queue *q, struct rq_qos *rqos) + + if (rqos->ops->debugfs_attrs) + blk_mq_debugfs_register_rqos(rqos); ++ ++ return 0; ++ebusy: ++ spin_unlock_irq(&q->queue_lock); ++ blk_mq_unfreeze_queue(q); ++ return -EBUSY; ++ + } + + static inline void rq_qos_del(struct request_queue *q, struct rq_qos *rqos) +diff --git a/block/blk-wbt.c b/block/blk-wbt.c +index 0c119be0e8133..ae6ea0b545799 100644 +--- a/block/blk-wbt.c ++++ b/block/blk-wbt.c +@@ -820,6 +820,7 @@ int wbt_init(struct request_queue *q) + { + struct rq_wb *rwb; + int i; ++ int ret; + + rwb = kzalloc(sizeof(*rwb), GFP_KERNEL); + if (!rwb) +@@ -846,7 +847,10 @@ int wbt_init(struct request_queue *q) + /* + * Assign rwb and add the stats callback. + */ +- rq_qos_add(q, &rwb->rqos); ++ ret = rq_qos_add(q, &rwb->rqos); ++ if (ret) ++ goto err_free; ++ + blk_stat_add_callback(q, rwb->cb); + + rwb->min_lat_nsec = wbt_default_latency_nsec(q); +@@ -855,4 +859,10 @@ int wbt_init(struct request_queue *q) + wbt_set_write_cache(q, test_bit(QUEUE_FLAG_WC, &q->queue_flags)); + + return 0; ++ ++err_free: ++ blk_stat_free_callback(rwb->cb); ++ kfree(rwb); ++ return ret; ++ + } +diff --git a/crypto/Kconfig b/crypto/Kconfig +index f0743ac4e8205..db260ccfba51b 100644 +--- a/crypto/Kconfig ++++ b/crypto/Kconfig +@@ -684,26 +684,8 @@ config CRYPTO_BLAKE2B + + See https://blake2.net for further information. + +-config CRYPTO_BLAKE2S +- tristate "BLAKE2s digest algorithm" +- select CRYPTO_LIB_BLAKE2S_GENERIC +- select CRYPTO_HASH +- help +- Implementation of cryptographic hash function BLAKE2s +- optimized for 8-32bit platforms and can produce digests of any size +- between 1 to 32. The keyed hash is also implemented. +- +- This module provides the following algorithms: +- +- - blake2s-128 +- - blake2s-160 +- - blake2s-224 +- - blake2s-256 +- +- See https://blake2.net for further information. +- + config CRYPTO_BLAKE2S_X86 +- tristate "BLAKE2s digest algorithm (x86 accelerated version)" ++ bool "BLAKE2s digest algorithm (x86 accelerated version)" + depends on X86 && 64BIT + select CRYPTO_LIB_BLAKE2S_GENERIC + select CRYPTO_ARCH_HAVE_LIB_BLAKE2S +diff --git a/crypto/Makefile b/crypto/Makefile +index 78b5ab05d6ed5..429591ffeb5da 100644 +--- a/crypto/Makefile ++++ b/crypto/Makefile +@@ -83,7 +83,6 @@ obj-$(CONFIG_CRYPTO_STREEBOG) += streebog_generic.o + obj-$(CONFIG_CRYPTO_WP512) += wp512.o + CFLAGS_wp512.o := $(call cc-option,-fno-schedule-insns) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79149 + obj-$(CONFIG_CRYPTO_BLAKE2B) += blake2b_generic.o +-obj-$(CONFIG_CRYPTO_BLAKE2S) += blake2s_generic.o + obj-$(CONFIG_CRYPTO_GF128MUL) += gf128mul.o + obj-$(CONFIG_CRYPTO_ECB) += ecb.o + obj-$(CONFIG_CRYPTO_CBC) += cbc.o +diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c +index 7c9e6be35c30c..2f8352e888602 100644 +--- a/crypto/asymmetric_keys/public_key.c ++++ b/crypto/asymmetric_keys/public_key.c +@@ -304,6 +304,10 @@ static int cert_sig_digest_update(const struct public_key_signature *sig, + + BUG_ON(!sig->data); + ++ /* SM2 signatures always use the SM3 hash algorithm */ ++ if (!sig->hash_algo || strcmp(sig->hash_algo, "sm3") != 0) ++ return -EINVAL; ++ + ret = sm2_compute_z_digest(tfm_pkey, SM2_DEFAULT_USERID, + SM2_DEFAULT_USERID_LEN, dgst); + if (ret) +@@ -414,8 +418,7 @@ int public_key_verify_signature(const struct public_key *pkey, + if (ret) + goto error_free_key; + +- if (sig->pkey_algo && strcmp(sig->pkey_algo, "sm2") == 0 && +- sig->data_size) { ++ if (strcmp(pkey->pkey_algo, "sm2") == 0 && sig->data_size) { + ret = cert_sig_digest_update(sig, tfm); + if (ret) + goto error_free_key; +diff --git a/crypto/blake2s_generic.c b/crypto/blake2s_generic.c +deleted file mode 100644 +index 5f96a21f87883..0000000000000 +--- a/crypto/blake2s_generic.c ++++ /dev/null +@@ -1,75 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 OR MIT +-/* +- * shash interface to the generic implementation of BLAKE2s +- * +- * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. +- */ +- +-#include <crypto/internal/blake2s.h> +-#include <crypto/internal/hash.h> +- +-#include <linux/types.h> +-#include <linux/kernel.h> +-#include <linux/module.h> +- +-static int crypto_blake2s_update_generic(struct shash_desc *desc, +- const u8 *in, unsigned int inlen) +-{ +- return crypto_blake2s_update(desc, in, inlen, true); +-} +- +-static int crypto_blake2s_final_generic(struct shash_desc *desc, u8 *out) +-{ +- return crypto_blake2s_final(desc, out, true); +-} +- +-#define BLAKE2S_ALG(name, driver_name, digest_size) \ +- { \ +- .base.cra_name = name, \ +- .base.cra_driver_name = driver_name, \ +- .base.cra_priority = 100, \ +- .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, \ +- .base.cra_blocksize = BLAKE2S_BLOCK_SIZE, \ +- .base.cra_ctxsize = sizeof(struct blake2s_tfm_ctx), \ +- .base.cra_module = THIS_MODULE, \ +- .digestsize = digest_size, \ +- .setkey = crypto_blake2s_setkey, \ +- .init = crypto_blake2s_init, \ +- .update = crypto_blake2s_update_generic, \ +- .final = crypto_blake2s_final_generic, \ +- .descsize = sizeof(struct blake2s_state), \ +- } +- +-static struct shash_alg blake2s_algs[] = { +- BLAKE2S_ALG("blake2s-128", "blake2s-128-generic", +- BLAKE2S_128_HASH_SIZE), +- BLAKE2S_ALG("blake2s-160", "blake2s-160-generic", +- BLAKE2S_160_HASH_SIZE), +- BLAKE2S_ALG("blake2s-224", "blake2s-224-generic", +- BLAKE2S_224_HASH_SIZE), +- BLAKE2S_ALG("blake2s-256", "blake2s-256-generic", +- BLAKE2S_256_HASH_SIZE), +-}; +- +-static int __init blake2s_mod_init(void) +-{ +- return crypto_register_shashes(blake2s_algs, ARRAY_SIZE(blake2s_algs)); +-} +- +-static void __exit blake2s_mod_exit(void) +-{ +- crypto_unregister_shashes(blake2s_algs, ARRAY_SIZE(blake2s_algs)); +-} +- +-subsys_initcall(blake2s_mod_init); +-module_exit(blake2s_mod_exit); +- +-MODULE_ALIAS_CRYPTO("blake2s-128"); +-MODULE_ALIAS_CRYPTO("blake2s-128-generic"); +-MODULE_ALIAS_CRYPTO("blake2s-160"); +-MODULE_ALIAS_CRYPTO("blake2s-160-generic"); +-MODULE_ALIAS_CRYPTO("blake2s-224"); +-MODULE_ALIAS_CRYPTO("blake2s-224-generic"); +-MODULE_ALIAS_CRYPTO("blake2s-256"); +-MODULE_ALIAS_CRYPTO("blake2s-256-generic"); +-MODULE_LICENSE("GPL v2"); +diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c +index 00149657a4bc1..3362897bf61b9 100644 +--- a/crypto/tcrypt.c ++++ b/crypto/tcrypt.c +@@ -1863,10 +1863,6 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb) + ret += tcrypt_test("rmd160"); + break; + +- case 41: +- ret += tcrypt_test("blake2s-256"); +- break; +- + case 42: + ret += tcrypt_test("blake2b-512"); + break; +@@ -2434,10 +2430,6 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb) + test_hash_speed("rmd160", sec, generic_hash_speed_template); + if (mode > 300 && mode < 400) break; + fallthrough; +- case 316: +- test_hash_speed("blake2s-256", sec, generic_hash_speed_template); +- if (mode > 300 && mode < 400) break; +- fallthrough; + case 317: + test_hash_speed("blake2b-512", sec, generic_hash_speed_template); + if (mode > 300 && mode < 400) break; +@@ -2546,10 +2538,6 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb) + test_ahash_speed("rmd160", sec, generic_hash_speed_template); + if (mode > 400 && mode < 500) break; + fallthrough; +- case 416: +- test_ahash_speed("blake2s-256", sec, generic_hash_speed_template); +- if (mode > 400 && mode < 500) break; +- fallthrough; + case 417: + test_ahash_speed("blake2b-512", sec, generic_hash_speed_template); + if (mode > 400 && mode < 500) break; +diff --git a/crypto/testmgr.c b/crypto/testmgr.c +index 70f69f0910c9e..163a1283a866a 100644 +--- a/crypto/testmgr.c ++++ b/crypto/testmgr.c +@@ -4329,30 +4329,6 @@ static const struct alg_test_desc alg_test_descs[] = { + .suite = { + .hash = __VECS(blake2b_512_tv_template) + } +- }, { +- .alg = "blake2s-128", +- .test = alg_test_hash, +- .suite = { +- .hash = __VECS(blakes2s_128_tv_template) +- } +- }, { +- .alg = "blake2s-160", +- .test = alg_test_hash, +- .suite = { +- .hash = __VECS(blakes2s_160_tv_template) +- } +- }, { +- .alg = "blake2s-224", +- .test = alg_test_hash, +- .suite = { +- .hash = __VECS(blakes2s_224_tv_template) +- } +- }, { +- .alg = "blake2s-256", +- .test = alg_test_hash, +- .suite = { +- .hash = __VECS(blakes2s_256_tv_template) +- } + }, { + .alg = "cbc(aes)", + .test = alg_test_skcipher, +diff --git a/crypto/testmgr.h b/crypto/testmgr.h +index e6fca34b5b257..2be20a590a606 100644 +--- a/crypto/testmgr.h ++++ b/crypto/testmgr.h +@@ -32583,221 +32583,4 @@ static const struct hash_testvec blake2b_512_tv_template[] = {{ + 0xae, 0x15, 0x81, 0x15, 0xd0, 0x88, 0xa0, 0x3c, }, + }}; + +-static const struct hash_testvec blakes2s_128_tv_template[] = {{ +- .digest = (u8[]){ 0x64, 0x55, 0x0d, 0x6f, 0xfe, 0x2c, 0x0a, 0x01, +- 0xa1, 0x4a, 0xba, 0x1e, 0xad, 0xe0, 0x20, 0x0c, }, +-}, { +- .plaintext = blake2_ordered_sequence, +- .psize = 64, +- .digest = (u8[]){ 0xdc, 0x66, 0xca, 0x8f, 0x03, 0x86, 0x58, 0x01, +- 0xb0, 0xff, 0xe0, 0x6e, 0xd8, 0xa1, 0xa9, 0x0e, }, +-}, { +- .ksize = 16, +- .key = blake2_ordered_sequence, +- .plaintext = blake2_ordered_sequence, +- .psize = 1, +- .digest = (u8[]){ 0x88, 0x1e, 0x42, 0xe7, 0xbb, 0x35, 0x80, 0x82, +- 0x63, 0x7c, 0x0a, 0x0f, 0xd7, 0xec, 0x6c, 0x2f, }, +-}, { +- .ksize = 32, +- .key = blake2_ordered_sequence, +- .plaintext = blake2_ordered_sequence, +- .psize = 7, +- .digest = (u8[]){ 0xcf, 0x9e, 0x07, 0x2a, 0xd5, 0x22, 0xf2, 0xcd, +- 0xa2, 0xd8, 0x25, 0x21, 0x80, 0x86, 0x73, 0x1c, }, +-}, { +- .ksize = 1, +- .key = "B", +- .plaintext = blake2_ordered_sequence, +- .psize = 15, +- .digest = (u8[]){ 0xf6, 0x33, 0x5a, 0x2c, 0x22, 0xa0, 0x64, 0xb2, +- 0xb6, 0x3f, 0xeb, 0xbc, 0xd1, 0xc3, 0xe5, 0xb2, }, +-}, { +- .ksize = 16, +- .key = blake2_ordered_sequence, +- .plaintext = blake2_ordered_sequence, +- .psize = 247, +- .digest = (u8[]){ 0x72, 0x66, 0x49, 0x60, 0xf9, 0x4a, 0xea, 0xbe, +- 0x1f, 0xf4, 0x60, 0xce, 0xb7, 0x81, 0xcb, 0x09, }, +-}, { +- .ksize = 32, +- .key = blake2_ordered_sequence, +- .plaintext = blake2_ordered_sequence, +- .psize = 256, +- .digest = (u8[]){ 0xd5, 0xa4, 0x0e, 0xc3, 0x16, 0xc7, 0x51, 0xa6, +- 0x3c, 0xd0, 0xd9, 0x11, 0x57, 0xfa, 0x1e, 0xbb, }, +-}}; +- +-static const struct hash_testvec blakes2s_160_tv_template[] = {{ +- .plaintext = blake2_ordered_sequence, +- .psize = 7, +- .digest = (u8[]){ 0xb4, 0xf2, 0x03, 0x49, 0x37, 0xed, 0xb1, 0x3e, +- 0x5b, 0x2a, 0xca, 0x64, 0x82, 0x74, 0xf6, 0x62, +- 0xe3, 0xf2, 0x84, 0xff, }, +-}, { +- .plaintext = blake2_ordered_sequence, +- .psize = 256, +- .digest = (u8[]){ 0xaa, 0x56, 0x9b, 0xdc, 0x98, 0x17, 0x75, 0xf2, +- 0xb3, 0x68, 0x83, 0xb7, 0x9b, 0x8d, 0x48, 0xb1, +- 0x9b, 0x2d, 0x35, 0x05, }, +-}, { +- .ksize = 1, +- .key = "B", +- .digest = (u8[]){ 0x50, 0x16, 0xe7, 0x0c, 0x01, 0xd0, 0xd3, 0xc3, +- 0xf4, 0x3e, 0xb1, 0x6e, 0x97, 0xa9, 0x4e, 0xd1, +- 0x79, 0x65, 0x32, 0x93, }, +-}, { +- .ksize = 32, +- .key = blake2_ordered_sequence, +- .plaintext = blake2_ordered_sequence, +- .psize = 1, +- .digest = (u8[]){ 0x1c, 0x2b, 0xcd, 0x9a, 0x68, 0xca, 0x8c, 0x71, +- 0x90, 0x29, 0x6c, 0x54, 0xfa, 0x56, 0x4a, 0xef, +- 0xa2, 0x3a, 0x56, 0x9c, }, +-}, { +- .ksize = 16, +- .key = blake2_ordered_sequence, +- .plaintext = blake2_ordered_sequence, +- .psize = 15, +- .digest = (u8[]){ 0x36, 0xc3, 0x5f, 0x9a, 0xdc, 0x7e, 0xbf, 0x19, +- 0x68, 0xaa, 0xca, 0xd8, 0x81, 0xbf, 0x09, 0x34, +- 0x83, 0x39, 0x0f, 0x30, }, +-}, { +- .ksize = 1, +- .key = "B", +- .plaintext = blake2_ordered_sequence, +- .psize = 64, +- .digest = (u8[]){ 0x86, 0x80, 0x78, 0xa4, 0x14, 0xec, 0x03, 0xe5, +- 0xb6, 0x9a, 0x52, 0x0e, 0x42, 0xee, 0x39, 0x9d, +- 0xac, 0xa6, 0x81, 0x63, }, +-}, { +- .ksize = 32, +- .key = blake2_ordered_sequence, +- .plaintext = blake2_ordered_sequence, +- .psize = 247, +- .digest = (u8[]){ 0x2d, 0xd8, 0xd2, 0x53, 0x66, 0xfa, 0xa9, 0x01, +- 0x1c, 0x9c, 0xaf, 0xa3, 0xe2, 0x9d, 0x9b, 0x10, +- 0x0a, 0xf6, 0x73, 0xe8, }, +-}}; +- +-static const struct hash_testvec blakes2s_224_tv_template[] = {{ +- .plaintext = blake2_ordered_sequence, +- .psize = 1, +- .digest = (u8[]){ 0x61, 0xb9, 0x4e, 0xc9, 0x46, 0x22, 0xa3, 0x91, +- 0xd2, 0xae, 0x42, 0xe6, 0x45, 0x6c, 0x90, 0x12, +- 0xd5, 0x80, 0x07, 0x97, 0xb8, 0x86, 0x5a, 0xfc, +- 0x48, 0x21, 0x97, 0xbb, }, +-}, { +- .plaintext = blake2_ordered_sequence, +- .psize = 247, +- .digest = (u8[]){ 0x9e, 0xda, 0xc7, 0x20, 0x2c, 0xd8, 0x48, 0x2e, +- 0x31, 0x94, 0xab, 0x46, 0x6d, 0x94, 0xd8, 0xb4, +- 0x69, 0xcd, 0xae, 0x19, 0x6d, 0x9e, 0x41, 0xcc, +- 0x2b, 0xa4, 0xd5, 0xf6, }, +-}, { +- .ksize = 16, +- .key = blake2_ordered_sequence, +- .digest = (u8[]){ 0x32, 0xc0, 0xac, 0xf4, 0x3b, 0xd3, 0x07, 0x9f, +- 0xbe, 0xfb, 0xfa, 0x4d, 0x6b, 0x4e, 0x56, 0xb3, +- 0xaa, 0xd3, 0x27, 0xf6, 0x14, 0xbf, 0xb9, 0x32, +- 0xa7, 0x19, 0xfc, 0xb8, }, +-}, { +- .ksize = 1, +- .key = "B", +- .plaintext = blake2_ordered_sequence, +- .psize = 7, +- .digest = (u8[]){ 0x73, 0xad, 0x5e, 0x6d, 0xb9, 0x02, 0x8e, 0x76, +- 0xf2, 0x66, 0x42, 0x4b, 0x4c, 0xfa, 0x1f, 0xe6, +- 0x2e, 0x56, 0x40, 0xe5, 0xa2, 0xb0, 0x3c, 0xe8, +- 0x7b, 0x45, 0xfe, 0x05, }, +-}, { +- .ksize = 32, +- .key = blake2_ordered_sequence, +- .plaintext = blake2_ordered_sequence, +- .psize = 15, +- .digest = (u8[]){ 0x16, 0x60, 0xfb, 0x92, 0x54, 0xb3, 0x6e, 0x36, +- 0x81, 0xf4, 0x16, 0x41, 0xc3, 0x3d, 0xd3, 0x43, +- 0x84, 0xed, 0x10, 0x6f, 0x65, 0x80, 0x7a, 0x3e, +- 0x25, 0xab, 0xc5, 0x02, }, +-}, { +- .ksize = 16, +- .key = blake2_ordered_sequence, +- .plaintext = blake2_ordered_sequence, +- .psize = 64, +- .digest = (u8[]){ 0xca, 0xaa, 0x39, 0x67, 0x9c, 0xf7, 0x6b, 0xc7, +- 0xb6, 0x82, 0xca, 0x0e, 0x65, 0x36, 0x5b, 0x7c, +- 0x24, 0x00, 0xfa, 0x5f, 0xda, 0x06, 0x91, 0x93, +- 0x6a, 0x31, 0x83, 0xb5, }, +-}, { +- .ksize = 1, +- .key = "B", +- .plaintext = blake2_ordered_sequence, +- .psize = 256, +- .digest = (u8[]){ 0x90, 0x02, 0x26, 0xb5, 0x06, 0x9c, 0x36, 0x86, +- 0x94, 0x91, 0x90, 0x1e, 0x7d, 0x2a, 0x71, 0xb2, +- 0x48, 0xb5, 0xe8, 0x16, 0xfd, 0x64, 0x33, 0x45, +- 0xb3, 0xd7, 0xec, 0xcc, }, +-}}; +- +-static const struct hash_testvec blakes2s_256_tv_template[] = {{ +- .plaintext = blake2_ordered_sequence, +- .psize = 15, +- .digest = (u8[]){ 0xd9, 0x7c, 0x82, 0x8d, 0x81, 0x82, 0xa7, 0x21, +- 0x80, 0xa0, 0x6a, 0x78, 0x26, 0x83, 0x30, 0x67, +- 0x3f, 0x7c, 0x4e, 0x06, 0x35, 0x94, 0x7c, 0x04, +- 0xc0, 0x23, 0x23, 0xfd, 0x45, 0xc0, 0xa5, 0x2d, }, +-}, { +- .ksize = 32, +- .key = blake2_ordered_sequence, +- .digest = (u8[]){ 0x48, 0xa8, 0x99, 0x7d, 0xa4, 0x07, 0x87, 0x6b, +- 0x3d, 0x79, 0xc0, 0xd9, 0x23, 0x25, 0xad, 0x3b, +- 0x89, 0xcb, 0xb7, 0x54, 0xd8, 0x6a, 0xb7, 0x1a, +- 0xee, 0x04, 0x7a, 0xd3, 0x45, 0xfd, 0x2c, 0x49, }, +-}, { +- .ksize = 1, +- .key = "B", +- .plaintext = blake2_ordered_sequence, +- .psize = 1, +- .digest = (u8[]){ 0x22, 0x27, 0xae, 0xaa, 0x6e, 0x81, 0x56, 0x03, +- 0xa7, 0xe3, 0xa1, 0x18, 0xa5, 0x9a, 0x2c, 0x18, +- 0xf4, 0x63, 0xbc, 0x16, 0x70, 0xf1, 0xe7, 0x4b, +- 0x00, 0x6d, 0x66, 0x16, 0xae, 0x9e, 0x74, 0x4e, }, +-}, { +- .ksize = 16, +- .key = blake2_ordered_sequence, +- .plaintext = blake2_ordered_sequence, +- .psize = 7, +- .digest = (u8[]){ 0x58, 0x5d, 0xa8, 0x60, 0x1c, 0xa4, 0xd8, 0x03, +- 0x86, 0x86, 0x84, 0x64, 0xd7, 0xa0, 0x8e, 0x15, +- 0x2f, 0x05, 0xa2, 0x1b, 0xbc, 0xef, 0x7a, 0x34, +- 0xb3, 0xc5, 0xbc, 0x4b, 0xf0, 0x32, 0xeb, 0x12, }, +-}, { +- .ksize = 32, +- .key = blake2_ordered_sequence, +- .plaintext = blake2_ordered_sequence, +- .psize = 64, +- .digest = (u8[]){ 0x89, 0x75, 0xb0, 0x57, 0x7f, 0xd3, 0x55, 0x66, +- 0xd7, 0x50, 0xb3, 0x62, 0xb0, 0x89, 0x7a, 0x26, +- 0xc3, 0x99, 0x13, 0x6d, 0xf0, 0x7b, 0xab, 0xab, +- 0xbd, 0xe6, 0x20, 0x3f, 0xf2, 0x95, 0x4e, 0xd4, }, +-}, { +- .ksize = 1, +- .key = "B", +- .plaintext = blake2_ordered_sequence, +- .psize = 247, +- .digest = (u8[]){ 0x2e, 0x74, 0x1c, 0x1d, 0x03, 0xf4, 0x9d, 0x84, +- 0x6f, 0xfc, 0x86, 0x32, 0x92, 0x49, 0x7e, 0x66, +- 0xd7, 0xc3, 0x10, 0x88, 0xfe, 0x28, 0xb3, 0xe0, +- 0xbf, 0x50, 0x75, 0xad, 0x8e, 0xa4, 0xe6, 0xb2, }, +-}, { +- .ksize = 16, +- .key = blake2_ordered_sequence, +- .plaintext = blake2_ordered_sequence, +- .psize = 256, +- .digest = (u8[]){ 0xb9, 0xd2, 0x81, 0x0e, 0x3a, 0xb1, 0x62, 0x9b, +- 0xad, 0x44, 0x05, 0xf4, 0x92, 0x2e, 0x99, 0xc1, +- 0x4a, 0x47, 0xbb, 0x5b, 0x6f, 0xb2, 0x96, 0xed, +- 0xd5, 0x06, 0xb5, 0x3a, 0x7c, 0x7a, 0x65, 0x1d, }, +-}}; +- + #endif /* _CRYPTO_TESTMGR_H */ +diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c +index 30b1f511c2af0..f609f9d62efdd 100644 +--- a/drivers/acpi/acpi_lpss.c ++++ b/drivers/acpi/acpi_lpss.c +@@ -403,6 +403,9 @@ static int register_device_clock(struct acpi_device *adev, + if (!lpss_clk_dev) + lpt_register_clock_device(); + ++ if (IS_ERR(lpss_clk_dev)) ++ return PTR_ERR(lpss_clk_dev); ++ + clk_data = platform_get_drvdata(lpss_clk_dev); + if (!clk_data) + return -ENODEV; +diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c +index 2882450c443ed..2e0ab898cce3b 100644 +--- a/drivers/acpi/apei/einj.c ++++ b/drivers/acpi/apei/einj.c +@@ -544,6 +544,8 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, + ((region_intersects(base_addr, size, IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE) + != REGION_INTERSECTS) && + (region_intersects(base_addr, size, IORESOURCE_MEM, IORES_DESC_PERSISTENT_MEMORY) ++ != REGION_INTERSECTS) && ++ (region_intersects(base_addr, size, IORESOURCE_MEM, IORES_DESC_SOFT_RESERVED) + != REGION_INTERSECTS))) + return -EINVAL; + +diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c +index 0c8330ed1ffd5..06b0184fa9121 100644 +--- a/drivers/acpi/apei/ghes.c ++++ b/drivers/acpi/apei/ghes.c +@@ -1457,33 +1457,35 @@ static struct platform_driver ghes_platform_driver = { + .remove = ghes_remove, + }; + +-static int __init ghes_init(void) ++void __init ghes_init(void) + { + int rc; + ++ sdei_init(); ++ + if (acpi_disabled) +- return -ENODEV; ++ return; + + switch (hest_disable) { + case HEST_NOT_FOUND: +- return -ENODEV; ++ return; + case HEST_DISABLED: + pr_info(GHES_PFX "HEST is not enabled!\n"); +- return -EINVAL; ++ return; + default: + break; + } + + if (ghes_disable) { + pr_info(GHES_PFX "GHES is not enabled!\n"); +- return -EINVAL; ++ return; + } + + ghes_nmi_init_cxt(); + + rc = platform_driver_register(&ghes_platform_driver); + if (rc) +- goto err; ++ return; + + rc = apei_osc_setup(); + if (rc == 0 && osc_sb_apei_support_acked) +@@ -1494,9 +1496,4 @@ static int __init ghes_init(void) + pr_info(GHES_PFX "APEI firmware first mode is enabled by APEI bit.\n"); + else + pr_info(GHES_PFX "Failed to enable APEI firmware first mode.\n"); +- +- return 0; +-err: +- return rc; + } +-device_initcall(ghes_init); +diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c +index 3500744e6862e..7774b603a7962 100644 +--- a/drivers/acpi/bus.c ++++ b/drivers/acpi/bus.c +@@ -1340,6 +1340,9 @@ static int __init acpi_init(void) + + pci_mmcfg_late_init(); + acpi_iort_init(); ++ acpi_viot_early_init(); ++ acpi_hest_init(); ++ ghes_init(); + acpi_scan_init(); + acpi_ec_init(); + acpi_debugfs_init(); +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index ed13410306845..7cc9183c8dc8e 100644 +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -597,33 +597,6 @@ static int pcc_data_alloc(int pcc_ss_id) + return 0; + } + +-/* Check if CPPC revision + num_ent combination is supported */ +-static bool is_cppc_supported(int revision, int num_ent) +-{ +- int expected_num_ent; +- +- switch (revision) { +- case CPPC_V2_REV: +- expected_num_ent = CPPC_V2_NUM_ENT; +- break; +- case CPPC_V3_REV: +- expected_num_ent = CPPC_V3_NUM_ENT; +- break; +- default: +- pr_debug("Firmware exports unsupported CPPC revision: %d\n", +- revision); +- return false; +- } +- +- if (expected_num_ent != num_ent) { +- pr_debug("Firmware exports %d entries. Expected: %d for CPPC rev:%d\n", +- num_ent, expected_num_ent, revision); +- return false; +- } +- +- return true; +-} +- + /* + * An example CPC table looks like the following. + * +@@ -723,7 +696,6 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr) + cpc_obj->type); + goto out_free; + } +- cpc_ptr->num_entries = num_ent; + + /* Second entry should be revision. */ + cpc_obj = &out_obj->package.elements[1]; +@@ -734,10 +706,32 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr) + cpc_obj->type); + goto out_free; + } +- cpc_ptr->version = cpc_rev; + +- if (!is_cppc_supported(cpc_rev, num_ent)) ++ if (cpc_rev < CPPC_V2_REV) { ++ pr_debug("Unsupported _CPC Revision (%d) for CPU:%d\n", cpc_rev, ++ pr->id); ++ goto out_free; ++ } ++ ++ /* ++ * Disregard _CPC if the number of entries in the return pachage is not ++ * as expected, but support future revisions being proper supersets of ++ * the v3 and only causing more entries to be returned by _CPC. ++ */ ++ if ((cpc_rev == CPPC_V2_REV && num_ent != CPPC_V2_NUM_ENT) || ++ (cpc_rev == CPPC_V3_REV && num_ent != CPPC_V3_NUM_ENT) || ++ (cpc_rev > CPPC_V3_REV && num_ent <= CPPC_V3_NUM_ENT)) { ++ pr_debug("Unexpected number of _CPC return package entries (%d) for CPU:%d\n", ++ num_ent, pr->id); + goto out_free; ++ } ++ if (cpc_rev > CPPC_V3_REV) { ++ num_ent = CPPC_V3_NUM_ENT; ++ cpc_rev = CPPC_V3_REV; ++ } ++ ++ cpc_ptr->num_entries = num_ent; ++ cpc_ptr->version = cpc_rev; + + /* Iterate through remaining entries in _CPC */ + for (i = 2; i < num_ent; i++) { +diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c +index 9b859ff976e89..4e583a8cb5626 100644 +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -183,7 +183,6 @@ static struct workqueue_struct *ec_wq; + static struct workqueue_struct *ec_query_wq; + + static int EC_FLAGS_CORRECT_ECDT; /* Needs ECDT port address correction */ +-static int EC_FLAGS_IGNORE_DSDT_GPE; /* Needs ECDT GPE as correction setting */ + static int EC_FLAGS_TRUST_DSDT_GPE; /* Needs DSDT GPE as correction setting */ + static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ + +@@ -1392,24 +1391,16 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) + if (ec->data_addr == 0 || ec->command_addr == 0) + return AE_OK; + +- if (boot_ec && boot_ec_is_ecdt && EC_FLAGS_IGNORE_DSDT_GPE) { +- /* +- * Always inherit the GPE number setting from the ECDT +- * EC. +- */ +- ec->gpe = boot_ec->gpe; +- } else { +- /* Get GPE bit assignment (EC events). */ +- /* TODO: Add support for _GPE returning a package */ +- status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp); +- if (ACPI_SUCCESS(status)) +- ec->gpe = tmp; ++ /* Get GPE bit assignment (EC events). */ ++ /* TODO: Add support for _GPE returning a package */ ++ status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp); ++ if (ACPI_SUCCESS(status)) ++ ec->gpe = tmp; ++ /* ++ * Errors are non-fatal, allowing for ACPI Reduced Hardware ++ * platforms which use GpioInt instead of GPE. ++ */ + +- /* +- * Errors are non-fatal, allowing for ACPI Reduced Hardware +- * platforms which use GpioInt instead of GPE. +- */ +- } + /* Use the global lock for all EC transactions? */ + tmp = 0; + acpi_evaluate_integer(handle, "_GLK", NULL, &tmp); +@@ -1847,60 +1838,12 @@ static int ec_honor_dsdt_gpe(const struct dmi_system_id *id) + return 0; + } + +-/* +- * Some DSDTs contain wrong GPE setting. +- * Asus FX502VD/VE, GL702VMK, X550VXK, X580VD +- * https://bugzilla.kernel.org/show_bug.cgi?id=195651 +- */ +-static int ec_honor_ecdt_gpe(const struct dmi_system_id *id) +-{ +- pr_debug("Detected system needing ignore DSDT GPE setting.\n"); +- EC_FLAGS_IGNORE_DSDT_GPE = 1; +- return 0; +-} +- + static const struct dmi_system_id ec_dmi_table[] __initconst = { + { + ec_correct_ecdt, "MSI MS-171F", { + DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star"), + DMI_MATCH(DMI_PRODUCT_NAME, "MS-171F"),}, NULL}, + { +- ec_honor_ecdt_gpe, "ASUS FX502VD", { +- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +- DMI_MATCH(DMI_PRODUCT_NAME, "FX502VD"),}, NULL}, +- { +- ec_honor_ecdt_gpe, "ASUS FX502VE", { +- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +- DMI_MATCH(DMI_PRODUCT_NAME, "FX502VE"),}, NULL}, +- { +- ec_honor_ecdt_gpe, "ASUS GL702VMK", { +- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +- DMI_MATCH(DMI_PRODUCT_NAME, "GL702VMK"),}, NULL}, +- { +- ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X505BA", { +- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +- DMI_MATCH(DMI_PRODUCT_NAME, "X505BA"),}, NULL}, +- { +- ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X505BP", { +- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +- DMI_MATCH(DMI_PRODUCT_NAME, "X505BP"),}, NULL}, +- { +- ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X542BA", { +- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +- DMI_MATCH(DMI_PRODUCT_NAME, "X542BA"),}, NULL}, +- { +- ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X542BP", { +- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +- DMI_MATCH(DMI_PRODUCT_NAME, "X542BP"),}, NULL}, +- { +- ec_honor_ecdt_gpe, "ASUS X550VXK", { +- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +- DMI_MATCH(DMI_PRODUCT_NAME, "X550VXK"),}, NULL}, +- { +- ec_honor_ecdt_gpe, "ASUS X580VD", { +- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +- DMI_MATCH(DMI_PRODUCT_NAME, "X580VD"),}, NULL}, +- { + /* https://bugzilla.kernel.org/show_bug.cgi?id=209989 */ + ec_honor_dsdt_gpe, "HP Pavilion Gaming Laptop 15-cx0xxx", { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), +@@ -2167,13 +2110,6 @@ static const struct dmi_system_id acpi_ec_no_wakeup[] = { + DMI_MATCH(DMI_PRODUCT_FAMILY, "Thinkpad X1 Carbon 6th"), + }, + }, +- { +- .ident = "ThinkPad X1 Carbon 6th", +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +- DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X1 Carbon 6th"), +- }, +- }, + { + .ident = "ThinkPad X1 Yoga 3rd", + .matches = { +diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c +index d7deedf3548e0..223aa010dd8da 100644 +--- a/drivers/acpi/pci_root.c ++++ b/drivers/acpi/pci_root.c +@@ -22,8 +22,6 @@ + #include <linux/slab.h> + #include <linux/dmi.h> + #include <linux/platform_data/x86/apple.h> +-#include <acpi/apei.h> /* for acpi_hest_init() */ +- + #include "internal.h" + + #define ACPI_PCI_ROOT_CLASS "pci_bridge" +@@ -938,7 +936,6 @@ out_release_info: + + void __init acpi_pci_root_init(void) + { +- acpi_hest_init(); + if (acpi_pci_disabled) + return; + +diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c +index aedcb92491f2e..dc880dad2ade5 100644 +--- a/drivers/acpi/processor_idle.c ++++ b/drivers/acpi/processor_idle.c +@@ -604,7 +604,7 @@ static DEFINE_RAW_SPINLOCK(c3_lock); + * @cx: Target state context + * @index: index of target state + */ +-static int acpi_idle_enter_bm(struct cpuidle_driver *drv, ++static int __cpuidle acpi_idle_enter_bm(struct cpuidle_driver *drv, + struct acpi_processor *pr, + struct acpi_processor_cx *cx, + int index) +@@ -661,7 +661,7 @@ static int acpi_idle_enter_bm(struct cpuidle_driver *drv, + return index; + } + +-static int acpi_idle_enter(struct cpuidle_device *dev, ++static int __cpuidle acpi_idle_enter(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) + { + struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu); +@@ -690,7 +690,7 @@ static int acpi_idle_enter(struct cpuidle_device *dev, + return index; + } + +-static int acpi_idle_enter_s2idle(struct cpuidle_device *dev, ++static int __cpuidle acpi_idle_enter_s2idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) + { + struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu); +diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c +index 07515139141e5..d7194047d2566 100644 +--- a/drivers/acpi/sleep.c ++++ b/drivers/acpi/sleep.c +@@ -361,6 +361,14 @@ static const struct dmi_system_id acpisleep_dmi_table[] __initconst = { + DMI_MATCH(DMI_PRODUCT_NAME, "80E3"), + }, + }, ++ { ++ .callback = init_nvs_save_s3, ++ .ident = "Lenovo G40-45", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "80E1"), ++ }, ++ }, + /* + * ThinkPad X1 Tablet(2016) cannot do suspend-to-idle using + * the Low Power S0 Idle firmware interface (see +diff --git a/drivers/acpi/viot.c b/drivers/acpi/viot.c +index d2256326c73ae..647f11cf165d7 100644 +--- a/drivers/acpi/viot.c ++++ b/drivers/acpi/viot.c +@@ -248,6 +248,26 @@ err_free: + return ret; + } + ++/** ++ * acpi_viot_early_init - Test the presence of VIOT and enable ACS ++ * ++ * If the VIOT does exist, ACS must be enabled. This cannot be ++ * done in acpi_viot_init() which is called after the bus scan ++ */ ++void __init acpi_viot_early_init(void) ++{ ++#ifdef CONFIG_PCI ++ acpi_status status; ++ struct acpi_table_header *hdr; ++ ++ status = acpi_get_table(ACPI_SIG_VIOT, 0, &hdr); ++ if (ACPI_FAILURE(status)) ++ return; ++ pci_request_acs(); ++ acpi_put_table(hdr); ++#endif ++} ++ + /** + * acpi_viot_init - Parse the VIOT table + * +@@ -319,12 +339,6 @@ static int viot_pci_dev_iommu_init(struct pci_dev *pdev, u16 dev_id, void *data) + epid = ((domain_nr - ep->segment_start) << 16) + + dev_id - ep->bdf_start + ep->endpoint_id; + +- /* +- * If we found a PCI range managed by the viommu, we're +- * the one that has to request ACS. +- */ +- pci_request_acs(); +- + return viot_dev_iommu_init(&pdev->dev, ep->viommu, + epid); + } +diff --git a/drivers/android/binder.c b/drivers/android/binder.c +index 99ae919255f4d..56a2387656a03 100644 +--- a/drivers/android/binder.c ++++ b/drivers/android/binder.c +@@ -170,8 +170,32 @@ static inline void binder_stats_created(enum binder_stat_types type) + atomic_inc(&binder_stats.obj_created[type]); + } + +-struct binder_transaction_log binder_transaction_log; +-struct binder_transaction_log binder_transaction_log_failed; ++struct binder_transaction_log_entry { ++ int debug_id; ++ int debug_id_done; ++ int call_type; ++ int from_proc; ++ int from_thread; ++ int target_handle; ++ int to_proc; ++ int to_thread; ++ int to_node; ++ int data_size; ++ int offsets_size; ++ int return_error_line; ++ uint32_t return_error; ++ uint32_t return_error_param; ++ char context_name[BINDERFS_MAX_NAME + 1]; ++}; ++ ++struct binder_transaction_log { ++ atomic_t cur; ++ bool full; ++ struct binder_transaction_log_entry entry[32]; ++}; ++ ++static struct binder_transaction_log binder_transaction_log; ++static struct binder_transaction_log binder_transaction_log_failed; + + static struct binder_transaction_log_entry *binder_transaction_log_add( + struct binder_transaction_log *log) +@@ -5801,8 +5825,7 @@ static void print_binder_proc_stats(struct seq_file *m, + print_binder_stats(m, " ", &proc->stats); + } + +- +-int binder_state_show(struct seq_file *m, void *unused) ++static int state_show(struct seq_file *m, void *unused) + { + struct binder_proc *proc; + struct binder_node *node; +@@ -5841,7 +5864,7 @@ int binder_state_show(struct seq_file *m, void *unused) + return 0; + } + +-int binder_stats_show(struct seq_file *m, void *unused) ++static int stats_show(struct seq_file *m, void *unused) + { + struct binder_proc *proc; + +@@ -5857,7 +5880,7 @@ int binder_stats_show(struct seq_file *m, void *unused) + return 0; + } + +-int binder_transactions_show(struct seq_file *m, void *unused) ++static int transactions_show(struct seq_file *m, void *unused) + { + struct binder_proc *proc; + +@@ -5913,7 +5936,7 @@ static void print_binder_transaction_log_entry(struct seq_file *m, + "\n" : " (incomplete)\n"); + } + +-int binder_transaction_log_show(struct seq_file *m, void *unused) ++static int transaction_log_show(struct seq_file *m, void *unused) + { + struct binder_transaction_log *log = m->private; + unsigned int log_cur = atomic_read(&log->cur); +@@ -5945,6 +5968,45 @@ const struct file_operations binder_fops = { + .release = binder_release, + }; + ++DEFINE_SHOW_ATTRIBUTE(state); ++DEFINE_SHOW_ATTRIBUTE(stats); ++DEFINE_SHOW_ATTRIBUTE(transactions); ++DEFINE_SHOW_ATTRIBUTE(transaction_log); ++ ++const struct binder_debugfs_entry binder_debugfs_entries[] = { ++ { ++ .name = "state", ++ .mode = 0444, ++ .fops = &state_fops, ++ .data = NULL, ++ }, ++ { ++ .name = "stats", ++ .mode = 0444, ++ .fops = &stats_fops, ++ .data = NULL, ++ }, ++ { ++ .name = "transactions", ++ .mode = 0444, ++ .fops = &transactions_fops, ++ .data = NULL, ++ }, ++ { ++ .name = "transaction_log", ++ .mode = 0444, ++ .fops = &transaction_log_fops, ++ .data = &binder_transaction_log, ++ }, ++ { ++ .name = "failed_transaction_log", ++ .mode = 0444, ++ .fops = &transaction_log_fops, ++ .data = &binder_transaction_log_failed, ++ }, ++ {} /* terminator */ ++}; ++ + static int __init init_binder_device(const char *name) + { + int ret; +@@ -5990,36 +6052,18 @@ static int __init binder_init(void) + atomic_set(&binder_transaction_log_failed.cur, ~0U); + + binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL); +- if (binder_debugfs_dir_entry_root) ++ if (binder_debugfs_dir_entry_root) { ++ const struct binder_debugfs_entry *db_entry; ++ ++ binder_for_each_debugfs_entry(db_entry) ++ debugfs_create_file(db_entry->name, ++ db_entry->mode, ++ binder_debugfs_dir_entry_root, ++ db_entry->data, ++ db_entry->fops); ++ + binder_debugfs_dir_entry_proc = debugfs_create_dir("proc", + binder_debugfs_dir_entry_root); +- +- if (binder_debugfs_dir_entry_root) { +- debugfs_create_file("state", +- 0444, +- binder_debugfs_dir_entry_root, +- NULL, +- &binder_state_fops); +- debugfs_create_file("stats", +- 0444, +- binder_debugfs_dir_entry_root, +- NULL, +- &binder_stats_fops); +- debugfs_create_file("transactions", +- 0444, +- binder_debugfs_dir_entry_root, +- NULL, +- &binder_transactions_fops); +- debugfs_create_file("transaction_log", +- 0444, +- binder_debugfs_dir_entry_root, +- &binder_transaction_log, +- &binder_transaction_log_fops); +- debugfs_create_file("failed_transaction_log", +- 0444, +- binder_debugfs_dir_entry_root, +- &binder_transaction_log_failed, +- &binder_transaction_log_fops); + } + + if (!IS_ENABLED(CONFIG_ANDROID_BINDERFS) && +diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c +index 47bc74a8c7b6f..b398909fda364 100644 +--- a/drivers/android/binder_alloc.c ++++ b/drivers/android/binder_alloc.c +@@ -213,7 +213,7 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, + + if (mm) { + mmap_read_lock(mm); +- vma = alloc->vma; ++ vma = vma_lookup(mm, alloc->vma_addr); + } + + if (!vma && need_mm) { +@@ -313,16 +313,15 @@ err_no_vma: + static inline void binder_alloc_set_vma(struct binder_alloc *alloc, + struct vm_area_struct *vma) + { +- if (vma) ++ unsigned long vm_start = 0; ++ ++ if (vma) { ++ vm_start = vma->vm_start; + alloc->vma_vm_mm = vma->vm_mm; +- /* +- * If we see alloc->vma is not NULL, buffer data structures set up +- * completely. Look at smp_rmb side binder_alloc_get_vma. +- * We also want to guarantee new alloc->vma_vm_mm is always visible +- * if alloc->vma is set. +- */ +- smp_wmb(); +- alloc->vma = vma; ++ } ++ ++ mmap_assert_write_locked(alloc->vma_vm_mm); ++ alloc->vma_addr = vm_start; + } + + static inline struct vm_area_struct *binder_alloc_get_vma( +@@ -330,11 +329,9 @@ static inline struct vm_area_struct *binder_alloc_get_vma( + { + struct vm_area_struct *vma = NULL; + +- if (alloc->vma) { +- /* Look at description in binder_alloc_set_vma */ +- smp_rmb(); +- vma = alloc->vma; +- } ++ if (alloc->vma_addr) ++ vma = vma_lookup(alloc->vma_vm_mm, alloc->vma_addr); ++ + return vma; + } + +@@ -817,7 +814,8 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) + + buffers = 0; + mutex_lock(&alloc->mutex); +- BUG_ON(alloc->vma); ++ BUG_ON(alloc->vma_addr && ++ vma_lookup(alloc->vma_vm_mm, alloc->vma_addr)); + + while ((n = rb_first(&alloc->allocated_buffers))) { + buffer = rb_entry(n, struct binder_buffer, rb_node); +diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h +index 7dea57a84c79b..1e4fd37af5e03 100644 +--- a/drivers/android/binder_alloc.h ++++ b/drivers/android/binder_alloc.h +@@ -100,7 +100,7 @@ struct binder_lru_page { + */ + struct binder_alloc { + struct mutex mutex; +- struct vm_area_struct *vma; ++ unsigned long vma_addr; + struct mm_struct *vma_vm_mm; + void __user *buffer; + struct list_head buffers; +diff --git a/drivers/android/binder_alloc_selftest.c b/drivers/android/binder_alloc_selftest.c +index c2b323bc3b3a5..43a881073a428 100644 +--- a/drivers/android/binder_alloc_selftest.c ++++ b/drivers/android/binder_alloc_selftest.c +@@ -287,7 +287,7 @@ void binder_selftest_alloc(struct binder_alloc *alloc) + if (!binder_selftest_run) + return; + mutex_lock(&binder_selftest_lock); +- if (!binder_selftest_run || !alloc->vma) ++ if (!binder_selftest_run || !alloc->vma_addr) + goto done; + pr_info("STARTED\n"); + binder_selftest_alloc_offset(alloc, end_offset, 0); +diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h +index d6b6b8cb73465..1ade9799c8d58 100644 +--- a/drivers/android/binder_internal.h ++++ b/drivers/android/binder_internal.h +@@ -107,41 +107,19 @@ static inline int __init init_binderfs(void) + } + #endif + +-int binder_stats_show(struct seq_file *m, void *unused); +-DEFINE_SHOW_ATTRIBUTE(binder_stats); +- +-int binder_state_show(struct seq_file *m, void *unused); +-DEFINE_SHOW_ATTRIBUTE(binder_state); +- +-int binder_transactions_show(struct seq_file *m, void *unused); +-DEFINE_SHOW_ATTRIBUTE(binder_transactions); +- +-int binder_transaction_log_show(struct seq_file *m, void *unused); +-DEFINE_SHOW_ATTRIBUTE(binder_transaction_log); +- +-struct binder_transaction_log_entry { +- int debug_id; +- int debug_id_done; +- int call_type; +- int from_proc; +- int from_thread; +- int target_handle; +- int to_proc; +- int to_thread; +- int to_node; +- int data_size; +- int offsets_size; +- int return_error_line; +- uint32_t return_error; +- uint32_t return_error_param; +- char context_name[BINDERFS_MAX_NAME + 1]; ++struct binder_debugfs_entry { ++ const char *name; ++ umode_t mode; ++ const struct file_operations *fops; ++ void *data; + }; + +-struct binder_transaction_log { +- atomic_t cur; +- bool full; +- struct binder_transaction_log_entry entry[32]; +-}; ++extern const struct binder_debugfs_entry binder_debugfs_entries[]; ++ ++#define binder_for_each_debugfs_entry(entry) \ ++ for ((entry) = binder_debugfs_entries; \ ++ (entry)->name; \ ++ (entry)++) + + enum binder_stat_types { + BINDER_STAT_PROC, +@@ -575,6 +553,4 @@ struct binder_object { + }; + }; + +-extern struct binder_transaction_log binder_transaction_log; +-extern struct binder_transaction_log binder_transaction_log_failed; + #endif /* _LINUX_BINDER_INTERNAL_H */ +diff --git a/drivers/android/binderfs.c b/drivers/android/binderfs.c +index e3605cdd43357..6d717ed76766e 100644 +--- a/drivers/android/binderfs.c ++++ b/drivers/android/binderfs.c +@@ -621,6 +621,7 @@ static int init_binder_features(struct super_block *sb) + static int init_binder_logs(struct super_block *sb) + { + struct dentry *binder_logs_root_dir, *dentry, *proc_log_dir; ++ const struct binder_debugfs_entry *db_entry; + struct binderfs_info *info; + int ret = 0; + +@@ -631,43 +632,15 @@ static int init_binder_logs(struct super_block *sb) + goto out; + } + +- dentry = binderfs_create_file(binder_logs_root_dir, "stats", +- &binder_stats_fops, NULL); +- if (IS_ERR(dentry)) { +- ret = PTR_ERR(dentry); +- goto out; +- } +- +- dentry = binderfs_create_file(binder_logs_root_dir, "state", +- &binder_state_fops, NULL); +- if (IS_ERR(dentry)) { +- ret = PTR_ERR(dentry); +- goto out; +- } +- +- dentry = binderfs_create_file(binder_logs_root_dir, "transactions", +- &binder_transactions_fops, NULL); +- if (IS_ERR(dentry)) { +- ret = PTR_ERR(dentry); +- goto out; +- } +- +- dentry = binderfs_create_file(binder_logs_root_dir, +- "transaction_log", +- &binder_transaction_log_fops, +- &binder_transaction_log); +- if (IS_ERR(dentry)) { +- ret = PTR_ERR(dentry); +- goto out; +- } +- +- dentry = binderfs_create_file(binder_logs_root_dir, +- "failed_transaction_log", +- &binder_transaction_log_fops, +- &binder_transaction_log_failed); +- if (IS_ERR(dentry)) { +- ret = PTR_ERR(dentry); +- goto out; ++ binder_for_each_debugfs_entry(db_entry) { ++ dentry = binderfs_create_file(binder_logs_root_dir, ++ db_entry->name, ++ db_entry->fops, ++ db_entry->data); ++ if (IS_ERR(dentry)) { ++ ret = PTR_ERR(dentry); ++ goto out; ++ } + } + + proc_log_dir = binderfs_create_dir(binder_logs_root_dir, "proc"); +diff --git a/drivers/base/dd.c b/drivers/base/dd.c +index 76ded601d0c1b..70e9ee8a10f79 100644 +--- a/drivers/base/dd.c ++++ b/drivers/base/dd.c +@@ -1094,6 +1094,7 @@ static void __driver_attach_async_helper(void *_dev, async_cookie_t cookie) + static int __driver_attach(struct device *dev, void *data) + { + struct device_driver *drv = data; ++ bool async = false; + int ret; + + /* +@@ -1132,9 +1133,11 @@ static int __driver_attach(struct device *dev, void *data) + if (!dev->driver) { + get_device(dev); + dev->p->async_driver = drv; +- async_schedule_dev(__driver_attach_async_helper, dev); ++ async = true; + } + device_unlock(dev); ++ if (async) ++ async_schedule_dev(__driver_attach_async_helper, dev); + return 0; + } + +diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c +index 0f2e42f368519..7f3d21e6fdfb3 100644 +--- a/drivers/base/power/domain.c ++++ b/drivers/base/power/domain.c +@@ -219,6 +219,9 @@ static void genpd_debug_remove(struct generic_pm_domain *genpd) + { + struct dentry *d; + ++ if (!genpd_debugfs_dir) ++ return; ++ + d = debugfs_lookup(genpd->name, genpd_debugfs_dir); + debugfs_remove(d); + } +diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c +index 187d779c8ca08..4c8b4101516c3 100644 +--- a/drivers/block/null_blk/main.c ++++ b/drivers/block/null_blk/main.c +@@ -1884,8 +1884,13 @@ static int null_add_dev(struct nullb_device *dev) + blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, nullb->q); + + mutex_lock(&lock); +- nullb->index = ida_simple_get(&nullb_indexes, 0, 0, GFP_KERNEL); +- dev->index = nullb->index; ++ rv = ida_simple_get(&nullb_indexes, 0, 0, GFP_KERNEL); ++ if (rv < 0) { ++ mutex_unlock(&lock); ++ goto out_cleanup_zone; ++ } ++ nullb->index = rv; ++ dev->index = rv; + mutex_unlock(&lock); + + blk_queue_logical_block_size(nullb->q, dev->blocksize); +@@ -1905,13 +1910,16 @@ static int null_add_dev(struct nullb_device *dev) + + rv = null_gendisk_register(nullb); + if (rv) +- goto out_cleanup_zone; ++ goto out_ida_free; + + mutex_lock(&lock); + list_add_tail(&nullb->list, &nullb_list); + mutex_unlock(&lock); + + return 0; ++ ++out_ida_free: ++ ida_free(&nullb_indexes, nullb->index); + out_cleanup_zone: + null_free_zoned_dev(dev); + out_cleanup_disk: +diff --git a/drivers/block/rnbd/rnbd-srv.c b/drivers/block/rnbd/rnbd-srv.c +index aafecfe970558..1896cde8135e4 100644 +--- a/drivers/block/rnbd/rnbd-srv.c ++++ b/drivers/block/rnbd/rnbd-srv.c +@@ -266,12 +266,12 @@ out: + static int create_sess(struct rtrs_srv *rtrs) + { + struct rnbd_srv_session *srv_sess; +- char sessname[NAME_MAX]; ++ char pathname[NAME_MAX]; + int err; + +- err = rtrs_srv_get_sess_name(rtrs, sessname, sizeof(sessname)); ++ err = rtrs_srv_get_path_name(rtrs, pathname, sizeof(pathname)); + if (err) { +- pr_err("rtrs_srv_get_sess_name(%s): %d\n", sessname, err); ++ pr_err("rtrs_srv_get_path_name(%s): %d\n", pathname, err); + + return err; + } +@@ -284,8 +284,8 @@ static int create_sess(struct rtrs_srv *rtrs) + offsetof(struct rnbd_dev_blk_io, bio), + BIOSET_NEED_BVECS); + if (err) { +- pr_err("Allocating srv_session for session %s failed\n", +- sessname); ++ pr_err("Allocating srv_session for path %s failed\n", ++ pathname); + kfree(srv_sess); + return err; + } +@@ -298,7 +298,7 @@ static int create_sess(struct rtrs_srv *rtrs) + mutex_unlock(&sess_lock); + + srv_sess->rtrs = rtrs; +- strscpy(srv_sess->sessname, sessname, sizeof(srv_sess->sessname)); ++ strscpy(srv_sess->sessname, pathname, sizeof(srv_sess->sessname)); + + rtrs_srv_set_sess_priv(rtrs, srv_sess); + +@@ -333,10 +333,11 @@ void rnbd_srv_sess_dev_force_close(struct rnbd_srv_sess_dev *sess_dev, + { + struct rnbd_srv_session *sess = sess_dev->sess; + +- sess_dev->keep_id = true; + /* It is already started to close by client's close message. */ + if (!mutex_trylock(&sess->lock)) + return; ++ ++ sess_dev->keep_id = true; + /* first remove sysfs itself to avoid deadlock */ + sysfs_remove_file_self(&sess_dev->kobj, &attr->attr); + rnbd_srv_destroy_dev_session_sysfs(sess_dev); +diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c +index 33eba3df4dd9a..78b50ac11e191 100644 +--- a/drivers/block/xen-blkback/xenbus.c ++++ b/drivers/block/xen-blkback/xenbus.c +@@ -156,6 +156,11 @@ static int xen_blkif_alloc_rings(struct xen_blkif *blkif) + return 0; + } + ++/* Enable the persistent grants feature. */ ++static bool feature_persistent = true; ++module_param(feature_persistent, bool, 0644); ++MODULE_PARM_DESC(feature_persistent, "Enables the persistent grants feature"); ++ + static struct xen_blkif *xen_blkif_alloc(domid_t domid) + { + struct xen_blkif *blkif; +@@ -471,12 +476,6 @@ static void xen_vbd_free(struct xen_vbd *vbd) + vbd->bdev = NULL; + } + +-/* Enable the persistent grants feature. */ +-static bool feature_persistent = true; +-module_param(feature_persistent, bool, 0644); +-MODULE_PARM_DESC(feature_persistent, +- "Enables the persistent grants feature"); +- + static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle, + unsigned major, unsigned minor, int readonly, + int cdrom) +@@ -522,8 +521,6 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle, + if (q && blk_queue_secure_erase(q)) + vbd->discard_secure = true; + +- vbd->feature_gnt_persistent = feature_persistent; +- + pr_debug("Successful creation of handle=%04x (dom=%u)\n", + handle, blkif->domid); + return 0; +@@ -1090,10 +1087,9 @@ static int connect_ring(struct backend_info *be) + xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol); + return -ENOSYS; + } +- if (blkif->vbd.feature_gnt_persistent) +- blkif->vbd.feature_gnt_persistent = +- xenbus_read_unsigned(dev->otherend, +- "feature-persistent", 0); ++ ++ blkif->vbd.feature_gnt_persistent = feature_persistent && ++ xenbus_read_unsigned(dev->otherend, "feature-persistent", 0); + + blkif->vbd.overflow_max_grants = 0; + +diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c +index f6f679702b832..23fc4c8f26039 100644 +--- a/drivers/block/xen-blkfront.c ++++ b/drivers/block/xen-blkfront.c +@@ -2014,8 +2014,6 @@ static int blkfront_probe(struct xenbus_device *dev, + info->vdevice = vdevice; + info->connected = BLKIF_STATE_DISCONNECTED; + +- info->feature_persistent = feature_persistent; +- + /* Front end dir is a number, which is used as the id. */ + info->handle = simple_strtoul(strrchr(dev->nodename, '/')+1, NULL, 0); + dev_set_drvdata(&dev->dev, info); +@@ -2309,7 +2307,7 @@ static void blkfront_gather_backend_features(struct blkfront_info *info) + if (xenbus_read_unsigned(info->xbdev->otherend, "feature-discard", 0)) + blkfront_setup_discard(info); + +- if (info->feature_persistent) ++ if (feature_persistent) + info->feature_persistent = + !!xenbus_read_unsigned(info->xbdev->otherend, + "feature-persistent", 0); +diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c +index 7249b91d9b91a..78afb9a348e70 100644 +--- a/drivers/bluetooth/hci_intel.c ++++ b/drivers/bluetooth/hci_intel.c +@@ -1217,7 +1217,11 @@ static struct platform_driver intel_driver = { + + int __init intel_init(void) + { +- platform_driver_register(&intel_driver); ++ int err; ++ ++ err = platform_driver_register(&intel_driver); ++ if (err) ++ return err; + + return hci_uart_register_proto(&intel_proto); + } +diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c +index 378f5d62a9912..e7eaa8784fee0 100644 +--- a/drivers/bus/hisi_lpc.c ++++ b/drivers/bus/hisi_lpc.c +@@ -503,13 +503,13 @@ static int hisi_lpc_acpi_probe(struct device *hostdev) + { + struct acpi_device *adev = ACPI_COMPANION(hostdev); + struct acpi_device *child; ++ struct platform_device *pdev; + int ret; + + /* Only consider the children of the host */ + list_for_each_entry(child, &adev->children, node) { + const char *hid = acpi_device_hid(child); + const struct hisi_lpc_acpi_cell *cell; +- struct platform_device *pdev; + const struct resource *res; + bool found = false; + int num_res; +@@ -571,22 +571,24 @@ static int hisi_lpc_acpi_probe(struct device *hostdev) + + ret = platform_device_add_resources(pdev, res, num_res); + if (ret) +- goto fail; ++ goto fail_put_device; + + ret = platform_device_add_data(pdev, cell->pdata, + cell->pdata_size); + if (ret) +- goto fail; ++ goto fail_put_device; + + ret = platform_device_add(pdev); + if (ret) +- goto fail; ++ goto fail_put_device; + + acpi_device_set_enumerated(child); + } + + return 0; + ++fail_put_device: ++ platform_device_put(pdev); + fail: + hisi_lpc_acpi_remove(hostdev); + return ret; +diff --git a/drivers/clk/mediatek/reset.c b/drivers/clk/mediatek/reset.c +index e562dc3c10a4b..d311da574499f 100644 +--- a/drivers/clk/mediatek/reset.c ++++ b/drivers/clk/mediatek/reset.c +@@ -25,7 +25,7 @@ static int mtk_reset_assert_set_clr(struct reset_controller_dev *rcdev, + struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev); + unsigned int reg = data->regofs + ((id / 32) << 4); + +- return regmap_write(data->regmap, reg, 1); ++ return regmap_write(data->regmap, reg, BIT(id % 32)); + } + + static int mtk_reset_deassert_set_clr(struct reset_controller_dev *rcdev, +@@ -34,7 +34,7 @@ static int mtk_reset_deassert_set_clr(struct reset_controller_dev *rcdev, + struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev); + unsigned int reg = data->regofs + ((id / 32) << 4) + 0x4; + +- return regmap_write(data->regmap, reg, 1); ++ return regmap_write(data->regmap, reg, BIT(id % 32)); + } + + static int mtk_reset_assert(struct reset_controller_dev *rcdev, +diff --git a/drivers/clk/qcom/camcc-sdm845.c b/drivers/clk/qcom/camcc-sdm845.c +index 1b2cefef7431d..a8a2cfa83290a 100644 +--- a/drivers/clk/qcom/camcc-sdm845.c ++++ b/drivers/clk/qcom/camcc-sdm845.c +@@ -1521,6 +1521,8 @@ static struct clk_branch cam_cc_sys_tmr_clk = { + }, + }; + ++static struct gdsc titan_top_gdsc; ++ + static struct gdsc bps_gdsc = { + .gdscr = 0x6004, + .pd = { +@@ -1554,6 +1556,7 @@ static struct gdsc ife_0_gdsc = { + .name = "ife_0_gdsc", + }, + .flags = POLL_CFG_GDSCR, ++ .parent = &titan_top_gdsc.pd, + .pwrsts = PWRSTS_OFF_ON, + }; + +@@ -1563,6 +1566,7 @@ static struct gdsc ife_1_gdsc = { + .name = "ife_1_gdsc", + }, + .flags = POLL_CFG_GDSCR, ++ .parent = &titan_top_gdsc.pd, + .pwrsts = PWRSTS_OFF_ON, + }; + +diff --git a/drivers/clk/qcom/camcc-sm8250.c b/drivers/clk/qcom/camcc-sm8250.c +index 439eaafdcc862..9b32c56a5bc5a 100644 +--- a/drivers/clk/qcom/camcc-sm8250.c ++++ b/drivers/clk/qcom/camcc-sm8250.c +@@ -2205,6 +2205,8 @@ static struct clk_branch cam_cc_sleep_clk = { + }, + }; + ++static struct gdsc titan_top_gdsc; ++ + static struct gdsc bps_gdsc = { + .gdscr = 0x7004, + .pd = { +@@ -2238,6 +2240,7 @@ static struct gdsc ife_0_gdsc = { + .name = "ife_0_gdsc", + }, + .flags = POLL_CFG_GDSCR, ++ .parent = &titan_top_gdsc.pd, + .pwrsts = PWRSTS_OFF_ON, + }; + +@@ -2247,6 +2250,7 @@ static struct gdsc ife_1_gdsc = { + .name = "ife_1_gdsc", + }, + .flags = POLL_CFG_GDSCR, ++ .parent = &titan_top_gdsc.pd, + .pwrsts = PWRSTS_OFF_ON, + }; + +@@ -2440,17 +2444,7 @@ static struct platform_driver cam_cc_sm8250_driver = { + }, + }; + +-static int __init cam_cc_sm8250_init(void) +-{ +- return platform_driver_register(&cam_cc_sm8250_driver); +-} +-subsys_initcall(cam_cc_sm8250_init); +- +-static void __exit cam_cc_sm8250_exit(void) +-{ +- platform_driver_unregister(&cam_cc_sm8250_driver); +-} +-module_exit(cam_cc_sm8250_exit); ++module_platform_driver(cam_cc_sm8250_driver); + + MODULE_DESCRIPTION("QTI CAMCC SM8250 Driver"); + MODULE_LICENSE("GPL v2"); +diff --git a/drivers/clk/qcom/clk-krait.c b/drivers/clk/qcom/clk-krait.c +index 59f1af415b580..90046428693c2 100644 +--- a/drivers/clk/qcom/clk-krait.c ++++ b/drivers/clk/qcom/clk-krait.c +@@ -32,11 +32,16 @@ static void __krait_mux_set_sel(struct krait_mux_clk *mux, int sel) + regval |= (sel & mux->mask) << (mux->shift + LPL_SHIFT); + } + krait_set_l2_indirect_reg(mux->offset, regval); +- spin_unlock_irqrestore(&krait_clock_reg_lock, flags); + + /* Wait for switch to complete. */ + mb(); + udelay(1); ++ ++ /* ++ * Unlock now to make sure the mux register is not ++ * modified while switching to the new parent. ++ */ ++ spin_unlock_irqrestore(&krait_clock_reg_lock, flags); + } + + static int krait_mux_set_parent(struct clk_hw *hw, u8 index) +diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c +index f675fd969c4de..c3823cc32edc6 100644 +--- a/drivers/clk/qcom/clk-rcg2.c ++++ b/drivers/clk/qcom/clk-rcg2.c +@@ -13,6 +13,7 @@ + #include <linux/rational.h> + #include <linux/regmap.h> + #include <linux/math64.h> ++#include <linux/minmax.h> + #include <linux/slab.h> + + #include <asm/div64.h> +@@ -405,7 +406,7 @@ static int clk_rcg2_get_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) + static int clk_rcg2_set_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) + { + struct clk_rcg2 *rcg = to_clk_rcg2(hw); +- u32 notn_m, n, m, d, not2d, mask, duty_per; ++ u32 notn_m, n, m, d, not2d, mask, duty_per, cfg; + int ret; + + /* Duty-cycle cannot be modified for non-MND RCGs */ +@@ -416,6 +417,11 @@ static int clk_rcg2_set_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) + + regmap_read(rcg->clkr.regmap, RCG_N_OFFSET(rcg), ¬n_m); + regmap_read(rcg->clkr.regmap, RCG_M_OFFSET(rcg), &m); ++ regmap_read(rcg->clkr.regmap, RCG_CFG_OFFSET(rcg), &cfg); ++ ++ /* Duty-cycle cannot be modified if MND divider is in bypass mode. */ ++ if (!(cfg & CFG_MODE_MASK)) ++ return -EINVAL; + + n = (~(notn_m) + m) & mask; + +@@ -424,9 +430,11 @@ static int clk_rcg2_set_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) + /* Calculate 2d value */ + d = DIV_ROUND_CLOSEST(n * duty_per * 2, 100); + +- /* Check bit widths of 2d. If D is too big reduce duty cycle. */ +- if (d > mask) +- d = mask; ++ /* ++ * Check bit widths of 2d. If D is too big reduce duty cycle. ++ * Also make sure it is never zero. ++ */ ++ d = clamp_val(d, 1, mask); + + if ((d / 2) > (n - m)) + d = (n - m) * 2; +diff --git a/drivers/clk/qcom/gcc-ipq8074.c b/drivers/clk/qcom/gcc-ipq8074.c +index 541016db3c4bb..2c2ecfc5e61f5 100644 +--- a/drivers/clk/qcom/gcc-ipq8074.c ++++ b/drivers/clk/qcom/gcc-ipq8074.c +@@ -1788,8 +1788,10 @@ static struct clk_regmap_div nss_port4_tx_div_clk_src = { + static const struct freq_tbl ftbl_nss_port5_rx_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(25000000, P_UNIPHY1_RX, 12.5, 0, 0), ++ F(25000000, P_UNIPHY0_RX, 5, 0, 0), + F(78125000, P_UNIPHY1_RX, 4, 0, 0), + F(125000000, P_UNIPHY1_RX, 2.5, 0, 0), ++ F(125000000, P_UNIPHY0_RX, 1, 0, 0), + F(156250000, P_UNIPHY1_RX, 2, 0, 0), + F(312500000, P_UNIPHY1_RX, 1, 0, 0), + { } +@@ -1828,8 +1830,10 @@ static struct clk_regmap_div nss_port5_rx_div_clk_src = { + static const struct freq_tbl ftbl_nss_port5_tx_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(25000000, P_UNIPHY1_TX, 12.5, 0, 0), ++ F(25000000, P_UNIPHY0_TX, 5, 0, 0), + F(78125000, P_UNIPHY1_TX, 4, 0, 0), + F(125000000, P_UNIPHY1_TX, 2.5, 0, 0), ++ F(125000000, P_UNIPHY0_TX, 1, 0, 0), + F(156250000, P_UNIPHY1_TX, 2, 0, 0), + F(312500000, P_UNIPHY1_TX, 1, 0, 0), + { } +@@ -1867,8 +1871,10 @@ static struct clk_regmap_div nss_port5_tx_div_clk_src = { + + static const struct freq_tbl ftbl_nss_port6_rx_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), ++ F(25000000, P_UNIPHY2_RX, 5, 0, 0), + F(25000000, P_UNIPHY2_RX, 12.5, 0, 0), + F(78125000, P_UNIPHY2_RX, 4, 0, 0), ++ F(125000000, P_UNIPHY2_RX, 1, 0, 0), + F(125000000, P_UNIPHY2_RX, 2.5, 0, 0), + F(156250000, P_UNIPHY2_RX, 2, 0, 0), + F(312500000, P_UNIPHY2_RX, 1, 0, 0), +@@ -1907,8 +1913,10 @@ static struct clk_regmap_div nss_port6_rx_div_clk_src = { + + static const struct freq_tbl ftbl_nss_port6_tx_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), ++ F(25000000, P_UNIPHY2_TX, 5, 0, 0), + F(25000000, P_UNIPHY2_TX, 12.5, 0, 0), + F(78125000, P_UNIPHY2_TX, 4, 0, 0), ++ F(125000000, P_UNIPHY2_TX, 1, 0, 0), + F(125000000, P_UNIPHY2_TX, 2.5, 0, 0), + F(156250000, P_UNIPHY2_TX, 2, 0, 0), + F(312500000, P_UNIPHY2_TX, 1, 0, 0), +@@ -3346,6 +3354,7 @@ static struct clk_branch gcc_nssnoc_ubi1_ahb_clk = { + + static struct clk_branch gcc_ubi0_ahb_clk = { + .halt_reg = 0x6820c, ++ .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x6820c, + .enable_mask = BIT(0), +@@ -3363,6 +3372,7 @@ static struct clk_branch gcc_ubi0_ahb_clk = { + + static struct clk_branch gcc_ubi0_axi_clk = { + .halt_reg = 0x68200, ++ .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x68200, + .enable_mask = BIT(0), +@@ -3380,6 +3390,7 @@ static struct clk_branch gcc_ubi0_axi_clk = { + + static struct clk_branch gcc_ubi0_nc_axi_clk = { + .halt_reg = 0x68204, ++ .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x68204, + .enable_mask = BIT(0), +@@ -3397,6 +3408,7 @@ static struct clk_branch gcc_ubi0_nc_axi_clk = { + + static struct clk_branch gcc_ubi0_core_clk = { + .halt_reg = 0x68210, ++ .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x68210, + .enable_mask = BIT(0), +@@ -3414,6 +3426,7 @@ static struct clk_branch gcc_ubi0_core_clk = { + + static struct clk_branch gcc_ubi0_mpt_clk = { + .halt_reg = 0x68208, ++ .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x68208, + .enable_mask = BIT(0), +@@ -3431,6 +3444,7 @@ static struct clk_branch gcc_ubi0_mpt_clk = { + + static struct clk_branch gcc_ubi1_ahb_clk = { + .halt_reg = 0x6822c, ++ .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x6822c, + .enable_mask = BIT(0), +@@ -3448,6 +3462,7 @@ static struct clk_branch gcc_ubi1_ahb_clk = { + + static struct clk_branch gcc_ubi1_axi_clk = { + .halt_reg = 0x68220, ++ .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x68220, + .enable_mask = BIT(0), +@@ -3465,6 +3480,7 @@ static struct clk_branch gcc_ubi1_axi_clk = { + + static struct clk_branch gcc_ubi1_nc_axi_clk = { + .halt_reg = 0x68224, ++ .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x68224, + .enable_mask = BIT(0), +@@ -3482,6 +3498,7 @@ static struct clk_branch gcc_ubi1_nc_axi_clk = { + + static struct clk_branch gcc_ubi1_core_clk = { + .halt_reg = 0x68230, ++ .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x68230, + .enable_mask = BIT(0), +@@ -3499,6 +3516,7 @@ static struct clk_branch gcc_ubi1_core_clk = { + + static struct clk_branch gcc_ubi1_mpt_clk = { + .halt_reg = 0x68228, ++ .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x68228, + .enable_mask = BIT(0), +@@ -4371,6 +4389,33 @@ static struct clk_branch gcc_pcie0_axi_s_bridge_clk = { + }, + }; + ++static const struct alpha_pll_config ubi32_pll_config = { ++ .l = 0x4e, ++ .config_ctl_val = 0x200d4aa8, ++ .config_ctl_hi_val = 0x3c2, ++ .main_output_mask = BIT(0), ++ .aux_output_mask = BIT(1), ++ .pre_div_val = 0x0, ++ .pre_div_mask = BIT(12), ++ .post_div_val = 0x0, ++ .post_div_mask = GENMASK(9, 8), ++}; ++ ++static const struct alpha_pll_config nss_crypto_pll_config = { ++ .l = 0x3e, ++ .alpha = 0x0, ++ .alpha_hi = 0x80, ++ .config_ctl_val = 0x4001055b, ++ .main_output_mask = BIT(0), ++ .pre_div_val = 0x0, ++ .pre_div_mask = GENMASK(14, 12), ++ .post_div_val = 0x1 << 8, ++ .post_div_mask = GENMASK(11, 8), ++ .vco_mask = GENMASK(21, 20), ++ .vco_val = 0x0, ++ .alpha_en_mask = BIT(24), ++}; ++ + static struct clk_hw *gcc_ipq8074_hws[] = { + &gpll0_out_main_div2.hw, + &gpll6_out_main_div2.hw, +@@ -4772,7 +4817,20 @@ static const struct qcom_cc_desc gcc_ipq8074_desc = { + + static int gcc_ipq8074_probe(struct platform_device *pdev) + { +- return qcom_cc_probe(pdev, &gcc_ipq8074_desc); ++ struct regmap *regmap; ++ ++ regmap = qcom_cc_map(pdev, &gcc_ipq8074_desc); ++ if (IS_ERR(regmap)) ++ return PTR_ERR(regmap); ++ ++ /* SW Workaround for UBI32 Huayra PLL */ ++ regmap_update_bits(regmap, 0x2501c, BIT(26), BIT(26)); ++ ++ clk_alpha_pll_configure(&ubi32_pll_main, regmap, &ubi32_pll_config); ++ clk_alpha_pll_configure(&nss_crypto_pll_main, regmap, ++ &nss_crypto_pll_config); ++ ++ return qcom_cc_really_probe(pdev, &gcc_ipq8074_desc, regmap); + } + + static struct platform_driver gcc_ipq8074_driver = { +diff --git a/drivers/clk/qcom/gcc-msm8939.c b/drivers/clk/qcom/gcc-msm8939.c +index 39ebb443ae3d5..de0022e5450de 100644 +--- a/drivers/clk/qcom/gcc-msm8939.c ++++ b/drivers/clk/qcom/gcc-msm8939.c +@@ -632,7 +632,7 @@ static struct clk_rcg2 system_noc_bfdcd_clk_src = { + }; + + static struct clk_rcg2 bimc_ddr_clk_src = { +- .cmd_rcgr = 0x32004, ++ .cmd_rcgr = 0x32024, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_bimc_map, + .clkr.hw.init = &(struct clk_init_data){ +@@ -644,6 +644,18 @@ static struct clk_rcg2 bimc_ddr_clk_src = { + }, + }; + ++static struct clk_rcg2 system_mm_noc_bfdcd_clk_src = { ++ .cmd_rcgr = 0x2600c, ++ .hid_width = 5, ++ .parent_map = gcc_xo_gpll0_gpll6a_map, ++ .clkr.hw.init = &(struct clk_init_data){ ++ .name = "system_mm_noc_bfdcd_clk_src", ++ .parent_data = gcc_xo_gpll0_gpll6a_parent_data, ++ .num_parents = 3, ++ .ops = &clk_rcg2_ops, ++ }, ++}; ++ + static const struct freq_tbl ftbl_gcc_camss_ahb_clk[] = { + F(40000000, P_GPLL0, 10, 1, 2), + F(80000000, P_GPLL0, 10, 0, 0), +@@ -1002,7 +1014,7 @@ static struct clk_rcg2 blsp1_uart2_apps_clk_src = { + }; + + static const struct freq_tbl ftbl_gcc_camss_cci_clk[] = { +- F(19200000, P_XO, 1, 0, 0), ++ F(19200000, P_XO, 1, 0, 0), + { } + }; + +@@ -2441,7 +2453,7 @@ static struct clk_branch gcc_camss_jpeg_axi_clk = { + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_jpeg_axi_clk", + .parent_data = &(const struct clk_parent_data){ +- .hw = &system_noc_bfdcd_clk_src.clkr.hw, ++ .hw = &system_mm_noc_bfdcd_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, +@@ -2645,7 +2657,7 @@ static struct clk_branch gcc_camss_vfe_axi_clk = { + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe_axi_clk", + .parent_data = &(const struct clk_parent_data){ +- .hw = &system_noc_bfdcd_clk_src.clkr.hw, ++ .hw = &system_mm_noc_bfdcd_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, +@@ -2801,7 +2813,7 @@ static struct clk_branch gcc_mdss_axi_clk = { + .hw.init = &(struct clk_init_data){ + .name = "gcc_mdss_axi_clk", + .parent_data = &(const struct clk_parent_data){ +- .hw = &system_noc_bfdcd_clk_src.clkr.hw, ++ .hw = &system_mm_noc_bfdcd_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, +@@ -3193,7 +3205,7 @@ static struct clk_branch gcc_mdp_tbu_clk = { + .hw.init = &(struct clk_init_data){ + .name = "gcc_mdp_tbu_clk", + .parent_data = &(const struct clk_parent_data){ +- .hw = &system_noc_bfdcd_clk_src.clkr.hw, ++ .hw = &system_mm_noc_bfdcd_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, +@@ -3211,7 +3223,7 @@ static struct clk_branch gcc_venus_tbu_clk = { + .hw.init = &(struct clk_init_data){ + .name = "gcc_venus_tbu_clk", + .parent_data = &(const struct clk_parent_data){ +- .hw = &system_noc_bfdcd_clk_src.clkr.hw, ++ .hw = &system_mm_noc_bfdcd_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, +@@ -3229,7 +3241,7 @@ static struct clk_branch gcc_vfe_tbu_clk = { + .hw.init = &(struct clk_init_data){ + .name = "gcc_vfe_tbu_clk", + .parent_data = &(const struct clk_parent_data){ +- .hw = &system_noc_bfdcd_clk_src.clkr.hw, ++ .hw = &system_mm_noc_bfdcd_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, +@@ -3247,7 +3259,7 @@ static struct clk_branch gcc_jpeg_tbu_clk = { + .hw.init = &(struct clk_init_data){ + .name = "gcc_jpeg_tbu_clk", + .parent_data = &(const struct clk_parent_data){ +- .hw = &system_noc_bfdcd_clk_src.clkr.hw, ++ .hw = &system_mm_noc_bfdcd_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, +@@ -3484,7 +3496,7 @@ static struct clk_branch gcc_venus0_axi_clk = { + .hw.init = &(struct clk_init_data){ + .name = "gcc_venus0_axi_clk", + .parent_data = &(const struct clk_parent_data){ +- .hw = &system_noc_bfdcd_clk_src.clkr.hw, ++ .hw = &system_mm_noc_bfdcd_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, +@@ -3623,6 +3635,7 @@ static struct clk_regmap *gcc_msm8939_clocks[] = { + [GPLL2_VOTE] = &gpll2_vote, + [PCNOC_BFDCD_CLK_SRC] = &pcnoc_bfdcd_clk_src.clkr, + [SYSTEM_NOC_BFDCD_CLK_SRC] = &system_noc_bfdcd_clk_src.clkr, ++ [SYSTEM_MM_NOC_BFDCD_CLK_SRC] = &system_mm_noc_bfdcd_clk_src.clkr, + [CAMSS_AHB_CLK_SRC] = &camss_ahb_clk_src.clkr, + [APSS_AHB_CLK_SRC] = &apss_ahb_clk_src.clkr, + [CSI0_CLK_SRC] = &csi0_clk_src.clkr, +diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c +index c99942f0e4d4c..abc0891fd96db 100644 +--- a/drivers/clk/renesas/r9a06g032-clocks.c ++++ b/drivers/clk/renesas/r9a06g032-clocks.c +@@ -286,8 +286,8 @@ static const struct r9a06g032_clkdesc r9a06g032_clocks[] = { + .name = "uart_group_012", + .type = K_BITSEL, + .source = 1 + R9A06G032_DIV_UART, +- /* R9A06G032_SYSCTRL_REG_PWRCTRL_PG1_PR2 */ +- .dual.sel = ((0xec / 4) << 5) | 24, ++ /* R9A06G032_SYSCTRL_REG_PWRCTRL_PG0_0 */ ++ .dual.sel = ((0x34 / 4) << 5) | 30, + .dual.group = 0, + }, + { +@@ -295,8 +295,8 @@ static const struct r9a06g032_clkdesc r9a06g032_clocks[] = { + .name = "uart_group_34567", + .type = K_BITSEL, + .source = 1 + R9A06G032_DIV_P2_PG, +- /* R9A06G032_SYSCTRL_REG_PWRCTRL_PG0_0 */ +- .dual.sel = ((0x34 / 4) << 5) | 30, ++ /* R9A06G032_SYSCTRL_REG_PWRCTRL_PG1_PR2 */ ++ .dual.sel = ((0xec / 4) << 5) | 24, + .dual.group = 1, + }, + D_UGATE(CLK_UART0, "clk_uart0", UART_GROUP_012, 0, 0, 0x1b2, 0x1b3, 0x1b4, 0x1b5), +diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c +index 70e2e6e373897..3c46ad8c3a1c5 100644 +--- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c ++++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c +@@ -151,6 +151,7 @@ dma_iv_error: + while (i >= 0) { + dma_unmap_single(ss->dev, rctx->p_iv[i], ivsize, DMA_TO_DEVICE); + memzero_explicit(sf->iv[i], ivsize); ++ i--; + } + return err; + } +diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c +index 6575305786436..47b5828e35c34 100644 +--- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c ++++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c +@@ -476,14 +476,32 @@ static int allocate_flows(struct sun8i_ss_dev *ss) + + ss->flows[i].biv = devm_kmalloc(ss->dev, AES_BLOCK_SIZE, + GFP_KERNEL | GFP_DMA); +- if (!ss->flows[i].biv) ++ if (!ss->flows[i].biv) { ++ err = -ENOMEM; + goto error_engine; ++ } + + for (j = 0; j < MAX_SG; j++) { + ss->flows[i].iv[j] = devm_kmalloc(ss->dev, AES_BLOCK_SIZE, + GFP_KERNEL | GFP_DMA); +- if (!ss->flows[i].iv[j]) ++ if (!ss->flows[i].iv[j]) { ++ err = -ENOMEM; + goto error_engine; ++ } ++ } ++ ++ /* the padding could be up to two block. */ ++ ss->flows[i].pad = devm_kmalloc(ss->dev, SHA256_BLOCK_SIZE * 2, ++ GFP_KERNEL | GFP_DMA); ++ if (!ss->flows[i].pad) { ++ err = -ENOMEM; ++ goto error_engine; ++ } ++ ss->flows[i].result = devm_kmalloc(ss->dev, SHA256_DIGEST_SIZE, ++ GFP_KERNEL | GFP_DMA); ++ if (!ss->flows[i].result) { ++ err = -ENOMEM; ++ goto error_engine; + } + + ss->flows[i].engine = crypto_engine_alloc_init(ss->dev, true); +diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c +index ca4f280af35d2..f89a580618aaa 100644 +--- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c ++++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c +@@ -342,18 +342,11 @@ int sun8i_ss_hash_run(struct crypto_engine *engine, void *breq) + if (digestsize == SHA224_DIGEST_SIZE) + digestsize = SHA256_DIGEST_SIZE; + +- /* the padding could be up to two block. */ +- pad = kzalloc(algt->alg.hash.halg.base.cra_blocksize * 2, GFP_KERNEL | GFP_DMA); +- if (!pad) +- return -ENOMEM; ++ result = ss->flows[rctx->flow].result; ++ pad = ss->flows[rctx->flow].pad; ++ memset(pad, 0, algt->alg.hash.halg.base.cra_blocksize * 2); + bf = (__le32 *)pad; + +- result = kzalloc(digestsize, GFP_KERNEL | GFP_DMA); +- if (!result) { +- kfree(pad); +- return -ENOMEM; +- } +- + for (i = 0; i < MAX_SG; i++) { + rctx->t_dst[i].addr = 0; + rctx->t_dst[i].len = 0; +@@ -449,8 +442,6 @@ int sun8i_ss_hash_run(struct crypto_engine *engine, void *breq) + + memcpy(areq->result, result, algt->alg.hash.halg.digestsize); + theend: +- kfree(pad); +- kfree(result); + local_bh_disable(); + crypto_finalize_hash_request(engine, breq, err); + local_bh_enable(); +diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h +index 57ada86538550..eb82ee5345ae1 100644 +--- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h ++++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h +@@ -123,6 +123,8 @@ struct sginfo { + * @stat_req: number of request done by this flow + * @iv: list of IV to use for each step + * @biv: buffer which contain the backuped IV ++ * @pad: padding buffer for hash operations ++ * @result: buffer for storing the result of hash operations + */ + struct sun8i_ss_flow { + struct crypto_engine *engine; +@@ -130,6 +132,8 @@ struct sun8i_ss_flow { + int status; + u8 *iv[MAX_SG]; + u8 *biv; ++ void *pad; ++ void *result; + #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG + unsigned long stat_req; + #endif +diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c +index 5040726fc119c..900727b5edda5 100644 +--- a/drivers/crypto/ccp/sev-dev.c ++++ b/drivers/crypto/ccp/sev-dev.c +@@ -314,7 +314,7 @@ static int __sev_platform_shutdown_locked(int *error) + struct sev_device *sev = psp_master->sev_data; + int ret; + +- if (sev->state == SEV_STATE_UNINIT) ++ if (!sev || sev->state == SEV_STATE_UNINIT) + return 0; + + ret = __sev_do_cmd_locked(SEV_CMD_SHUTDOWN, NULL, error); +@@ -388,6 +388,8 @@ static int sev_ioctl_do_platform_status(struct sev_issue_cmd *argp) + struct sev_user_data_status data; + int ret; + ++ memset(&data, 0, sizeof(data)); ++ + ret = __sev_do_cmd_locked(SEV_CMD_PLATFORM_STATUS, &data, &argp->error); + if (ret) + return ret; +@@ -441,7 +443,7 @@ static int sev_ioctl_do_pek_csr(struct sev_issue_cmd *argp, bool writable) + if (input.length > SEV_FW_BLOB_MAX_SIZE) + return -EFAULT; + +- blob = kmalloc(input.length, GFP_KERNEL); ++ blob = kzalloc(input.length, GFP_KERNEL); + if (!blob) + return -ENOMEM; + +@@ -665,7 +667,7 @@ static int sev_ioctl_do_get_id2(struct sev_issue_cmd *argp) + input_address = (void __user *)input.address; + + if (input.address && input.length) { +- id_blob = kmalloc(input.length, GFP_KERNEL); ++ id_blob = kzalloc(input.length, GFP_KERNEL); + if (!id_blob) + return -ENOMEM; + +@@ -784,14 +786,14 @@ static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp, bool writable) + if (input.cert_chain_len > SEV_FW_BLOB_MAX_SIZE) + return -EFAULT; + +- pdh_blob = kmalloc(input.pdh_cert_len, GFP_KERNEL); ++ pdh_blob = kzalloc(input.pdh_cert_len, GFP_KERNEL); + if (!pdh_blob) + return -ENOMEM; + + data.pdh_cert_address = __psp_pa(pdh_blob); + data.pdh_cert_len = input.pdh_cert_len; + +- cert_blob = kmalloc(input.cert_chain_len, GFP_KERNEL); ++ cert_blob = kzalloc(input.cert_chain_len, GFP_KERNEL); + if (!cert_blob) { + ret = -ENOMEM; + goto e_free_pdh; +diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c b/drivers/crypto/hisilicon/hpre/hpre_crypto.c +index 7ba7641723a0b..4062251fd1b68 100644 +--- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c ++++ b/drivers/crypto/hisilicon/hpre/hpre_crypto.c +@@ -252,7 +252,7 @@ static int hpre_prepare_dma_buf(struct hpre_asym_request *hpre_req, + if (unlikely(shift < 0)) + return -EINVAL; + +- ptr = dma_alloc_coherent(dev, ctx->key_sz, tmp, GFP_KERNEL); ++ ptr = dma_alloc_coherent(dev, ctx->key_sz, tmp, GFP_ATOMIC); + if (unlikely(!ptr)) + return -ENOMEM; + +diff --git a/drivers/crypto/hisilicon/sec/sec_algs.c b/drivers/crypto/hisilicon/sec/sec_algs.c +index 0a3c8f019b025..490e1542305e1 100644 +--- a/drivers/crypto/hisilicon/sec/sec_algs.c ++++ b/drivers/crypto/hisilicon/sec/sec_algs.c +@@ -449,7 +449,7 @@ static void sec_skcipher_alg_callback(struct sec_bd_info *sec_resp, + */ + } + +- mutex_lock(&ctx->queue->queuelock); ++ spin_lock_bh(&ctx->queue->queuelock); + /* Put the IV in place for chained cases */ + switch (ctx->cipher_alg) { + case SEC_C_AES_CBC_128: +@@ -509,7 +509,7 @@ static void sec_skcipher_alg_callback(struct sec_bd_info *sec_resp, + list_del(&backlog_req->backlog_head); + } + } +- mutex_unlock(&ctx->queue->queuelock); ++ spin_unlock_bh(&ctx->queue->queuelock); + + mutex_lock(&sec_req->lock); + list_del(&sec_req_el->head); +@@ -798,7 +798,7 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq, + */ + + /* Grab a big lock for a long time to avoid concurrency issues */ +- mutex_lock(&queue->queuelock); ++ spin_lock_bh(&queue->queuelock); + + /* + * Can go on to queue if we have space in either: +@@ -814,15 +814,15 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq, + ret = -EBUSY; + if ((skreq->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) { + list_add_tail(&sec_req->backlog_head, &ctx->backlog); +- mutex_unlock(&queue->queuelock); ++ spin_unlock_bh(&queue->queuelock); + goto out; + } + +- mutex_unlock(&queue->queuelock); ++ spin_unlock_bh(&queue->queuelock); + goto err_free_elements; + } + ret = sec_send_request(sec_req, queue); +- mutex_unlock(&queue->queuelock); ++ spin_unlock_bh(&queue->queuelock); + if (ret) + goto err_free_elements; + +@@ -881,7 +881,7 @@ static int sec_alg_skcipher_init(struct crypto_skcipher *tfm) + if (IS_ERR(ctx->queue)) + return PTR_ERR(ctx->queue); + +- mutex_init(&ctx->queue->queuelock); ++ spin_lock_init(&ctx->queue->queuelock); + ctx->queue->havesoftqueue = false; + + return 0; +diff --git a/drivers/crypto/hisilicon/sec/sec_drv.h b/drivers/crypto/hisilicon/sec/sec_drv.h +index 179a8250d691c..e2a50bf2234b9 100644 +--- a/drivers/crypto/hisilicon/sec/sec_drv.h ++++ b/drivers/crypto/hisilicon/sec/sec_drv.h +@@ -347,7 +347,7 @@ struct sec_queue { + DECLARE_BITMAP(unprocessed, SEC_QUEUE_LEN); + DECLARE_KFIFO_PTR(softqueue, typeof(struct sec_request_el *)); + bool havesoftqueue; +- struct mutex queuelock; ++ spinlock_t queuelock; + void *shadow[SEC_QUEUE_LEN]; + }; + +diff --git a/drivers/crypto/hisilicon/sec2/sec.h b/drivers/crypto/hisilicon/sec2/sec.h +index d97cf02b1df75..cff00fd297652 100644 +--- a/drivers/crypto/hisilicon/sec2/sec.h ++++ b/drivers/crypto/hisilicon/sec2/sec.h +@@ -119,7 +119,7 @@ struct sec_qp_ctx { + struct idr req_idr; + struct sec_alg_res res[QM_Q_DEPTH]; + struct sec_ctx *ctx; +- struct mutex req_lock; ++ spinlock_t req_lock; + struct list_head backlog; + struct hisi_acc_sgl_pool *c_in_pool; + struct hisi_acc_sgl_pool *c_out_pool; +diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c +index 090920ed50c8f..0d26eda36a526 100644 +--- a/drivers/crypto/hisilicon/sec2/sec_crypto.c ++++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c +@@ -124,11 +124,11 @@ static int sec_alloc_req_id(struct sec_req *req, struct sec_qp_ctx *qp_ctx) + { + int req_id; + +- mutex_lock(&qp_ctx->req_lock); ++ spin_lock_bh(&qp_ctx->req_lock); + + req_id = idr_alloc_cyclic(&qp_ctx->req_idr, NULL, + 0, QM_Q_DEPTH, GFP_ATOMIC); +- mutex_unlock(&qp_ctx->req_lock); ++ spin_unlock_bh(&qp_ctx->req_lock); + if (unlikely(req_id < 0)) { + dev_err(req->ctx->dev, "alloc req id fail!\n"); + return req_id; +@@ -153,9 +153,9 @@ static void sec_free_req_id(struct sec_req *req) + qp_ctx->req_list[req_id] = NULL; + req->qp_ctx = NULL; + +- mutex_lock(&qp_ctx->req_lock); ++ spin_lock_bh(&qp_ctx->req_lock); + idr_remove(&qp_ctx->req_idr, req_id); +- mutex_unlock(&qp_ctx->req_lock); ++ spin_unlock_bh(&qp_ctx->req_lock); + } + + static u8 pre_parse_finished_bd(struct bd_status *status, void *resp) +@@ -270,7 +270,7 @@ static int sec_bd_send(struct sec_ctx *ctx, struct sec_req *req) + !(req->flag & CRYPTO_TFM_REQ_MAY_BACKLOG)) + return -EBUSY; + +- mutex_lock(&qp_ctx->req_lock); ++ spin_lock_bh(&qp_ctx->req_lock); + ret = hisi_qp_send(qp_ctx->qp, &req->sec_sqe); + + if (ctx->fake_req_limit <= +@@ -278,10 +278,10 @@ static int sec_bd_send(struct sec_ctx *ctx, struct sec_req *req) + list_add_tail(&req->backlog_head, &qp_ctx->backlog); + atomic64_inc(&ctx->sec->debug.dfx.send_cnt); + atomic64_inc(&ctx->sec->debug.dfx.send_busy_cnt); +- mutex_unlock(&qp_ctx->req_lock); ++ spin_unlock_bh(&qp_ctx->req_lock); + return -EBUSY; + } +- mutex_unlock(&qp_ctx->req_lock); ++ spin_unlock_bh(&qp_ctx->req_lock); + + if (unlikely(ret == -EBUSY)) + return -ENOBUFS; +@@ -484,7 +484,7 @@ static int sec_create_qp_ctx(struct hisi_qm *qm, struct sec_ctx *ctx, + + qp->req_cb = sec_req_cb; + +- mutex_init(&qp_ctx->req_lock); ++ spin_lock_init(&qp_ctx->req_lock); + idr_init(&qp_ctx->req_idr); + INIT_LIST_HEAD(&qp_ctx->backlog); + +@@ -617,7 +617,7 @@ static int sec_auth_init(struct sec_ctx *ctx) + { + struct sec_auth_ctx *a_ctx = &ctx->a_ctx; + +- a_ctx->a_key = dma_alloc_coherent(ctx->dev, SEC_MAX_KEY_SIZE, ++ a_ctx->a_key = dma_alloc_coherent(ctx->dev, SEC_MAX_AKEY_SIZE, + &a_ctx->a_key_dma, GFP_KERNEL); + if (!a_ctx->a_key) + return -ENOMEM; +@@ -629,8 +629,8 @@ static void sec_auth_uninit(struct sec_ctx *ctx) + { + struct sec_auth_ctx *a_ctx = &ctx->a_ctx; + +- memzero_explicit(a_ctx->a_key, SEC_MAX_KEY_SIZE); +- dma_free_coherent(ctx->dev, SEC_MAX_KEY_SIZE, ++ memzero_explicit(a_ctx->a_key, SEC_MAX_AKEY_SIZE); ++ dma_free_coherent(ctx->dev, SEC_MAX_AKEY_SIZE, + a_ctx->a_key, a_ctx->a_key_dma); + } + +@@ -1373,7 +1373,7 @@ static struct sec_req *sec_back_req_clear(struct sec_ctx *ctx, + { + struct sec_req *backlog_req = NULL; + +- mutex_lock(&qp_ctx->req_lock); ++ spin_lock_bh(&qp_ctx->req_lock); + if (ctx->fake_req_limit >= + atomic_read(&qp_ctx->qp->qp_status.used) && + !list_empty(&qp_ctx->backlog)) { +@@ -1381,7 +1381,7 @@ static struct sec_req *sec_back_req_clear(struct sec_ctx *ctx, + typeof(*backlog_req), backlog_head); + list_del(&backlog_req->backlog_head); + } +- mutex_unlock(&qp_ctx->req_lock); ++ spin_unlock_bh(&qp_ctx->req_lock); + + return backlog_req; + } +diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.h b/drivers/crypto/hisilicon/sec2/sec_crypto.h +index 9f71c358a6d35..ee2edaf5058df 100644 +--- a/drivers/crypto/hisilicon/sec2/sec_crypto.h ++++ b/drivers/crypto/hisilicon/sec2/sec_crypto.h +@@ -7,6 +7,7 @@ + #define SEC_AIV_SIZE 12 + #define SEC_IV_SIZE 24 + #define SEC_MAX_KEY_SIZE 64 ++#define SEC_MAX_AKEY_SIZE 128 + #define SEC_COMM_SCENE 0 + #define SEC_MIN_BLOCK_SZ 1 + +diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c +index 9ff885d50edfc..389a7b51f1f38 100644 +--- a/drivers/crypto/inside-secure/safexcel.c ++++ b/drivers/crypto/inside-secure/safexcel.c +@@ -1831,6 +1831,8 @@ static const struct of_device_id safexcel_of_match_table[] = { + {}, + }; + ++MODULE_DEVICE_TABLE(of, safexcel_of_match_table); ++ + static struct platform_driver crypto_safexcel = { + .probe = safexcel_probe, + .remove = safexcel_remove, +diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c +index 53289927dd0d6..36b3fe1b6b0f9 100644 +--- a/drivers/dma/dw-edma/dw-edma-core.c ++++ b/drivers/dma/dw-edma/dw-edma-core.c +@@ -424,7 +424,7 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer) + chunk->ll_region.sz += burst->sz; + desc->alloc_sz += burst->sz; + +- if (chan->dir == EDMA_DIR_WRITE) { ++ if (dir == DMA_DEV_TO_MEM) { + burst->sar = src_addr; + if (xfer->type == EDMA_XFER_CYCLIC) { + burst->dar = xfer->xfer.cyclic.paddr; +diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c +index 2ddc31e64db03..da31e73d24d4c 100644 +--- a/drivers/dma/imx-dma.c ++++ b/drivers/dma/imx-dma.c +@@ -1047,7 +1047,7 @@ static int __init imxdma_probe(struct platform_device *pdev) + return -ENOMEM; + + imxdma->dev = &pdev->dev; +- imxdma->devtype = (enum imx_dma_type)of_device_get_match_data(&pdev->dev); ++ imxdma->devtype = (uintptr_t)of_device_get_match_data(&pdev->dev); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + imxdma->base = devm_ioremap_resource(&pdev->dev, res); +diff --git a/drivers/dma/sf-pdma/sf-pdma.c b/drivers/dma/sf-pdma/sf-pdma.c +index f12606aeff87c..ab0ad7a2f2015 100644 +--- a/drivers/dma/sf-pdma/sf-pdma.c ++++ b/drivers/dma/sf-pdma/sf-pdma.c +@@ -52,16 +52,6 @@ static inline struct sf_pdma_desc *to_sf_pdma_desc(struct virt_dma_desc *vd) + static struct sf_pdma_desc *sf_pdma_alloc_desc(struct sf_pdma_chan *chan) + { + struct sf_pdma_desc *desc; +- unsigned long flags; +- +- spin_lock_irqsave(&chan->lock, flags); +- +- if (chan->desc && !chan->desc->in_use) { +- spin_unlock_irqrestore(&chan->lock, flags); +- return chan->desc; +- } +- +- spin_unlock_irqrestore(&chan->lock, flags); + + desc = kzalloc(sizeof(*desc), GFP_NOWAIT); + if (!desc) +@@ -111,7 +101,6 @@ sf_pdma_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dest, dma_addr_t src, + desc->async_tx = vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); + + spin_lock_irqsave(&chan->vchan.lock, iflags); +- chan->desc = desc; + sf_pdma_fill_desc(desc, dest, src, len); + spin_unlock_irqrestore(&chan->vchan.lock, iflags); + +@@ -170,11 +159,17 @@ static size_t sf_pdma_desc_residue(struct sf_pdma_chan *chan, + unsigned long flags; + u64 residue = 0; + struct sf_pdma_desc *desc; +- struct dma_async_tx_descriptor *tx; ++ struct dma_async_tx_descriptor *tx = NULL; + + spin_lock_irqsave(&chan->vchan.lock, flags); + +- tx = &chan->desc->vdesc.tx; ++ list_for_each_entry(vd, &chan->vchan.desc_submitted, node) ++ if (vd->tx.cookie == cookie) ++ tx = &vd->tx; ++ ++ if (!tx) ++ goto out; ++ + if (cookie == tx->chan->completed_cookie) + goto out; + +@@ -241,6 +236,19 @@ static void sf_pdma_enable_request(struct sf_pdma_chan *chan) + writel(v, regs->ctrl); + } + ++static struct sf_pdma_desc *sf_pdma_get_first_pending_desc(struct sf_pdma_chan *chan) ++{ ++ struct virt_dma_chan *vchan = &chan->vchan; ++ struct virt_dma_desc *vdesc; ++ ++ if (list_empty(&vchan->desc_issued)) ++ return NULL; ++ ++ vdesc = list_first_entry(&vchan->desc_issued, struct virt_dma_desc, node); ++ ++ return container_of(vdesc, struct sf_pdma_desc, vdesc); ++} ++ + static void sf_pdma_xfer_desc(struct sf_pdma_chan *chan) + { + struct sf_pdma_desc *desc = chan->desc; +@@ -268,8 +276,11 @@ static void sf_pdma_issue_pending(struct dma_chan *dchan) + + spin_lock_irqsave(&chan->vchan.lock, flags); + +- if (vchan_issue_pending(&chan->vchan) && chan->desc) ++ if (!chan->desc && vchan_issue_pending(&chan->vchan)) { ++ /* vchan_issue_pending has made a check that desc in not NULL */ ++ chan->desc = sf_pdma_get_first_pending_desc(chan); + sf_pdma_xfer_desc(chan); ++ } + + spin_unlock_irqrestore(&chan->vchan.lock, flags); + } +@@ -298,6 +309,11 @@ static void sf_pdma_donebh_tasklet(struct tasklet_struct *t) + spin_lock_irqsave(&chan->vchan.lock, flags); + list_del(&chan->desc->vdesc.node); + vchan_cookie_complete(&chan->desc->vdesc); ++ ++ chan->desc = sf_pdma_get_first_pending_desc(chan); ++ if (chan->desc) ++ sf_pdma_xfer_desc(chan); ++ + spin_unlock_irqrestore(&chan->vchan.lock, flags); + } + +diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig +index cda7d7162cbbd..97ce31e667fca 100644 +--- a/drivers/firmware/Kconfig ++++ b/drivers/firmware/Kconfig +@@ -40,6 +40,7 @@ config ARM_SCPI_POWER_DOMAIN + config ARM_SDE_INTERFACE + bool "ARM Software Delegated Exception Interface (SDEI)" + depends on ARM64 ++ depends on ACPI_APEI_GHES + help + The Software Delegated Exception Interface (SDEI) is an ARM + standard for registering callbacks from the platform firmware +diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c +index ddf0b9ff9e15c..435d0e2658a42 100644 +--- a/drivers/firmware/arm_scpi.c ++++ b/drivers/firmware/arm_scpi.c +@@ -815,7 +815,7 @@ static int scpi_init_versions(struct scpi_drvinfo *info) + info->firmware_version = le32_to_cpu(caps.platform_version); + } + /* Ignore error if not implemented */ +- if (scpi_info->is_legacy && ret == -EOPNOTSUPP) ++ if (info->is_legacy && ret == -EOPNOTSUPP) + return 0; + + return ret; +@@ -913,13 +913,14 @@ static int scpi_probe(struct platform_device *pdev) + struct resource res; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; ++ struct scpi_drvinfo *scpi_drvinfo; + +- scpi_info = devm_kzalloc(dev, sizeof(*scpi_info), GFP_KERNEL); +- if (!scpi_info) ++ scpi_drvinfo = devm_kzalloc(dev, sizeof(*scpi_drvinfo), GFP_KERNEL); ++ if (!scpi_drvinfo) + return -ENOMEM; + + if (of_match_device(legacy_scpi_of_match, &pdev->dev)) +- scpi_info->is_legacy = true; ++ scpi_drvinfo->is_legacy = true; + + count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells"); + if (count < 0) { +@@ -927,19 +928,19 @@ static int scpi_probe(struct platform_device *pdev) + return -ENODEV; + } + +- scpi_info->channels = devm_kcalloc(dev, count, sizeof(struct scpi_chan), +- GFP_KERNEL); +- if (!scpi_info->channels) ++ scpi_drvinfo->channels = ++ devm_kcalloc(dev, count, sizeof(struct scpi_chan), GFP_KERNEL); ++ if (!scpi_drvinfo->channels) + return -ENOMEM; + +- ret = devm_add_action(dev, scpi_free_channels, scpi_info); ++ ret = devm_add_action(dev, scpi_free_channels, scpi_drvinfo); + if (ret) + return ret; + +- for (; scpi_info->num_chans < count; scpi_info->num_chans++) { ++ for (; scpi_drvinfo->num_chans < count; scpi_drvinfo->num_chans++) { + resource_size_t size; +- int idx = scpi_info->num_chans; +- struct scpi_chan *pchan = scpi_info->channels + idx; ++ int idx = scpi_drvinfo->num_chans; ++ struct scpi_chan *pchan = scpi_drvinfo->channels + idx; + struct mbox_client *cl = &pchan->cl; + struct device_node *shmem = of_parse_phandle(np, "shmem", idx); + +@@ -986,45 +987,53 @@ static int scpi_probe(struct platform_device *pdev) + return ret; + } + +- scpi_info->commands = scpi_std_commands; ++ scpi_drvinfo->commands = scpi_std_commands; + +- platform_set_drvdata(pdev, scpi_info); ++ platform_set_drvdata(pdev, scpi_drvinfo); + +- if (scpi_info->is_legacy) { ++ if (scpi_drvinfo->is_legacy) { + /* Replace with legacy variants */ + scpi_ops.clk_set_val = legacy_scpi_clk_set_val; +- scpi_info->commands = scpi_legacy_commands; ++ scpi_drvinfo->commands = scpi_legacy_commands; + + /* Fill priority bitmap */ + for (idx = 0; idx < ARRAY_SIZE(legacy_hpriority_cmds); idx++) + set_bit(legacy_hpriority_cmds[idx], +- scpi_info->cmd_priority); ++ scpi_drvinfo->cmd_priority); + } + +- ret = scpi_init_versions(scpi_info); ++ scpi_info = scpi_drvinfo; ++ ++ ret = scpi_init_versions(scpi_drvinfo); + if (ret) { + dev_err(dev, "incorrect or no SCP firmware found\n"); ++ scpi_info = NULL; + return ret; + } + +- if (scpi_info->is_legacy && !scpi_info->protocol_version && +- !scpi_info->firmware_version) ++ if (scpi_drvinfo->is_legacy && !scpi_drvinfo->protocol_version && ++ !scpi_drvinfo->firmware_version) + dev_info(dev, "SCP Protocol legacy pre-1.0 firmware\n"); + else + dev_info(dev, "SCP Protocol %lu.%lu Firmware %lu.%lu.%lu version\n", + FIELD_GET(PROTO_REV_MAJOR_MASK, +- scpi_info->protocol_version), ++ scpi_drvinfo->protocol_version), + FIELD_GET(PROTO_REV_MINOR_MASK, +- scpi_info->protocol_version), ++ scpi_drvinfo->protocol_version), + FIELD_GET(FW_REV_MAJOR_MASK, +- scpi_info->firmware_version), ++ scpi_drvinfo->firmware_version), + FIELD_GET(FW_REV_MINOR_MASK, +- scpi_info->firmware_version), ++ scpi_drvinfo->firmware_version), + FIELD_GET(FW_REV_PATCH_MASK, +- scpi_info->firmware_version)); +- scpi_info->scpi_ops = &scpi_ops; ++ scpi_drvinfo->firmware_version)); ++ ++ scpi_drvinfo->scpi_ops = &scpi_ops; + +- return devm_of_platform_populate(dev); ++ ret = devm_of_platform_populate(dev); ++ if (ret) ++ scpi_info = NULL; ++ ++ return ret; + } + + static const struct of_device_id scpi_of_match[] = { +diff --git a/drivers/firmware/arm_sdei.c b/drivers/firmware/arm_sdei.c +index a7e762c352f95..1e1a51510e83b 100644 +--- a/drivers/firmware/arm_sdei.c ++++ b/drivers/firmware/arm_sdei.c +@@ -1059,14 +1059,14 @@ static bool __init sdei_present_acpi(void) + return true; + } + +-static int __init sdei_init(void) ++void __init sdei_init(void) + { + struct platform_device *pdev; + int ret; + + ret = platform_driver_register(&sdei_driver); + if (ret || !sdei_present_acpi()) +- return ret; ++ return; + + pdev = platform_device_register_simple(sdei_driver.driver.name, + 0, NULL, 0); +@@ -1076,17 +1076,8 @@ static int __init sdei_init(void) + pr_info("Failed to register ACPI:SDEI platform device %d\n", + ret); + } +- +- return ret; + } + +-/* +- * On an ACPI system SDEI needs to be ready before HEST:GHES tries to register +- * its events. ACPI is initialised from a subsys_initcall(), GHES is initialised +- * by device_initcall(). We want to be called in the middle. +- */ +-subsys_initcall_sync(sdei_init); +- + int sdei_event_handler(struct pt_regs *regs, + struct sdei_registered_event *arg) + { +diff --git a/drivers/firmware/tegra/bpmp-debugfs.c b/drivers/firmware/tegra/bpmp-debugfs.c +index 3e9fa4b543588..1ed881a567d5c 100644 +--- a/drivers/firmware/tegra/bpmp-debugfs.c ++++ b/drivers/firmware/tegra/bpmp-debugfs.c +@@ -465,7 +465,7 @@ static int bpmp_populate_debugfs_inband(struct tegra_bpmp *bpmp, + mode |= attrs & DEBUGFS_S_IWUSR ? 0200 : 0; + dentry = debugfs_create_file(name, mode, parent, bpmp, + &bpmp_debug_fops); +- if (!dentry) { ++ if (IS_ERR(dentry)) { + err = -ENOMEM; + goto out; + } +@@ -716,7 +716,7 @@ static int bpmp_populate_dir(struct tegra_bpmp *bpmp, struct seqbuf *seqbuf, + + if (t & DEBUGFS_S_ISDIR) { + dentry = debugfs_create_dir(name, parent); +- if (!dentry) ++ if (IS_ERR(dentry)) + return -ENOMEM; + err = bpmp_populate_dir(bpmp, seqbuf, dentry, depth+1); + if (err < 0) +@@ -729,7 +729,7 @@ static int bpmp_populate_dir(struct tegra_bpmp *bpmp, struct seqbuf *seqbuf, + dentry = debugfs_create_file(name, mode, + parent, bpmp, + &debugfs_fops); +- if (!dentry) ++ if (IS_ERR(dentry)) + return -ENOMEM; + } + } +@@ -779,11 +779,11 @@ int tegra_bpmp_init_debugfs(struct tegra_bpmp *bpmp) + return 0; + + root = debugfs_create_dir("bpmp", NULL); +- if (!root) ++ if (IS_ERR(root)) + return -ENOMEM; + + bpmp->debugfs_mirror = debugfs_create_dir("debug", root); +- if (!bpmp->debugfs_mirror) { ++ if (IS_ERR(bpmp->debugfs_mirror)) { + err = -ENOMEM; + goto out; + } +diff --git a/drivers/fpga/altera-pr-ip-core.c b/drivers/fpga/altera-pr-ip-core.c +index dfdf21ed34c4e..c24b6fb2d7c37 100644 +--- a/drivers/fpga/altera-pr-ip-core.c ++++ b/drivers/fpga/altera-pr-ip-core.c +@@ -108,7 +108,7 @@ static int alt_pr_fpga_write(struct fpga_manager *mgr, const char *buf, + u32 *buffer_32 = (u32 *)buf; + size_t i = 0; + +- if (count <= 0) ++ if (!count) + return -EINVAL; + + /* Write out the complete 32-bit chunks */ +diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c +index 66e434f59f60c..7a96eb626a08b 100644 +--- a/drivers/gpio/gpiolib-of.c ++++ b/drivers/gpio/gpiolib-of.c +@@ -863,7 +863,8 @@ int of_mm_gpiochip_add_data(struct device_node *np, + if (mm_gc->save_regs) + mm_gc->save_regs(mm_gc); + +- mm_gc->gc.of_node = np; ++ of_node_put(mm_gc->gc.of_node); ++ mm_gc->gc.of_node = of_node_get(np); + + ret = gpiochip_add_data(gc, data); + if (ret) +@@ -871,6 +872,7 @@ int of_mm_gpiochip_add_data(struct device_node *np, + + return 0; + err2: ++ of_node_put(np); + iounmap(mm_gc->regs); + err1: + kfree(gc->label); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +index 21c02f817a848..c904269b3e148 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +@@ -1318,16 +1318,10 @@ void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev, + struct amdgpu_vm *vm) + { + struct amdkfd_process_info *process_info = vm->process_info; +- struct amdgpu_bo *pd = vm->root.bo; + + if (!process_info) + return; + +- /* Release eviction fence from PD */ +- amdgpu_bo_reserve(pd, false); +- amdgpu_bo_fence(pd, NULL, false); +- amdgpu_bo_unreserve(pd); +- + /* Update process info */ + mutex_lock(&process_info->lock); + process_info->n_vms--; +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +index cd0acbea75da6..d58ab9deb0280 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +@@ -341,7 +341,8 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev) + } + + /* disable all the possible outputs/crtcs before entering KMS mode */ +- if (!amdgpu_device_has_dc_support(adev) && !amdgpu_virtual_display) ++ if (!amdgpu_device_has_dc_support(adev) && !amdgpu_virtual_display && ++ !amdgpu_sriov_vf(adev)) + drm_helper_disable_unused_functions(adev_to_drm(adev)); + + drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +index 41d0b3a7b65d8..a0b1bf17cb74b 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +@@ -912,6 +912,10 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, + if (WARN_ON_ONCE(min_offset > max_offset)) + return -EINVAL; + ++ /* Check domain to be pinned to against preferred domains */ ++ if (bo->preferred_domains & domain) ++ domain = bo->preferred_domains & domain; ++ + /* A shared bo cannot be migrated to VRAM */ + if (bo->tbo.base.import_attach) { + if (domain & AMDGPU_GEM_DOMAIN_GTT) +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +index 8c2025584f1b4..7e3f6633f255d 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +@@ -1063,6 +1063,10 @@ static int adv7511_init_cec_regmap(struct adv7511 *adv) + ADV7511_CEC_I2C_ADDR_DEFAULT); + if (IS_ERR(adv->i2c_cec)) + return PTR_ERR(adv->i2c_cec); ++ ++ regmap_write(adv->regmap, ADV7511_REG_CEC_I2C_ADDR, ++ adv->i2c_cec->addr << 1); ++ + i2c_set_clientdata(adv->i2c_cec, adv); + + adv->regmap_cec = devm_regmap_init_i2c(adv->i2c_cec, +@@ -1267,9 +1271,6 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) + if (ret) + goto err_i2c_unregister_packet; + +- regmap_write(adv7511->regmap, ADV7511_REG_CEC_I2C_ADDR, +- adv7511->i2c_cec->addr << 1); +- + INIT_WORK(&adv7511->hpd_work, adv7511_hpd_work); + + if (i2c->irq) { +@@ -1378,10 +1379,21 @@ static struct i2c_driver adv7511_driver = { + + static int __init adv7511_init(void) + { +- if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) +- mipi_dsi_driver_register(&adv7533_dsi_driver); ++ int ret; + +- return i2c_add_driver(&adv7511_driver); ++ if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) { ++ ret = mipi_dsi_driver_register(&adv7533_dsi_driver); ++ if (ret) ++ return ret; ++ } ++ ++ ret = i2c_add_driver(&adv7511_driver); ++ if (ret) { ++ if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) ++ mipi_dsi_driver_unregister(&adv7533_dsi_driver); ++ } ++ ++ return ret; + } + module_init(adv7511_init); + +diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +index 010657ea7af78..c4454d0f6cad5 100644 +--- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c ++++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +@@ -997,7 +997,7 @@ static int lt9611uxc_remove(struct i2c_client *client) + struct lt9611uxc *lt9611uxc = i2c_get_clientdata(client); + + disable_irq(client->irq); +- flush_scheduled_work(); ++ cancel_work_sync(<9611uxc->work); + lt9611uxc_audio_exit(lt9611uxc); + drm_bridge_remove(<9611uxc->bridge); + +diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c +index c916f4b8907ef..b32295abd9e75 100644 +--- a/drivers/gpu/drm/bridge/panel.c ++++ b/drivers/gpu/drm/bridge/panel.c +@@ -9,6 +9,7 @@ + #include <drm/drm_connector.h> + #include <drm/drm_encoder.h> + #include <drm/drm_modeset_helper_vtables.h> ++#include <drm/drm_of.h> + #include <drm/drm_panel.h> + #include <drm/drm_print.h> + #include <drm/drm_probe_helper.h> +@@ -332,3 +333,39 @@ struct drm_connector *drm_panel_bridge_connector(struct drm_bridge *bridge) + return &panel_bridge->connector; + } + EXPORT_SYMBOL(drm_panel_bridge_connector); ++ ++#ifdef CONFIG_OF ++/** ++ * devm_drm_of_get_bridge - Return next bridge in the chain ++ * @dev: device to tie the bridge lifetime to ++ * @np: device tree node containing encoder output ports ++ * @port: port in the device tree node ++ * @endpoint: endpoint in the device tree node ++ * ++ * Given a DT node's port and endpoint number, finds the connected node ++ * and returns the associated bridge if any, or creates and returns a ++ * drm panel bridge instance if a panel is connected. ++ * ++ * Returns a pointer to the bridge if successful, or an error pointer ++ * otherwise. ++ */ ++struct drm_bridge *devm_drm_of_get_bridge(struct device *dev, ++ struct device_node *np, ++ u32 port, u32 endpoint) ++{ ++ struct drm_bridge *bridge; ++ struct drm_panel *panel; ++ int ret; ++ ++ ret = drm_of_find_panel_or_bridge(np, port, endpoint, ++ &panel, &bridge); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ if (panel) ++ bridge = devm_drm_panel_bridge_add(dev, panel); ++ ++ return bridge; ++} ++EXPORT_SYMBOL(devm_drm_of_get_bridge); ++#endif +diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c +index ec7745c31da07..ab0bce4a988c5 100644 +--- a/drivers/gpu/drm/bridge/sil-sii8620.c ++++ b/drivers/gpu/drm/bridge/sil-sii8620.c +@@ -605,7 +605,7 @@ static void *sii8620_burst_get_tx_buf(struct sii8620 *ctx, int len) + u8 *buf = &ctx->burst.tx_buf[ctx->burst.tx_count]; + int size = len + 2; + +- if (ctx->burst.tx_count + size > ARRAY_SIZE(ctx->burst.tx_buf)) { ++ if (ctx->burst.tx_count + size >= ARRAY_SIZE(ctx->burst.tx_buf)) { + dev_err(ctx->dev, "TX-BLK buffer exhausted\n"); + ctx->error = -EINVAL; + return NULL; +@@ -622,7 +622,7 @@ static u8 *sii8620_burst_get_rx_buf(struct sii8620 *ctx, int len) + u8 *buf = &ctx->burst.rx_buf[ctx->burst.rx_count]; + int size = len + 1; + +- if (ctx->burst.tx_count + size > ARRAY_SIZE(ctx->burst.tx_buf)) { ++ if (ctx->burst.rx_count + size >= ARRAY_SIZE(ctx->burst.rx_buf)) { + dev_err(ctx->dev, "RX-BLK buffer exhausted\n"); + ctx->error = -EINVAL; + return NULL; +diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c +index 23a6f90b694b3..14d6717429639 100644 +--- a/drivers/gpu/drm/bridge/tc358767.c ++++ b/drivers/gpu/drm/bridge/tc358767.c +@@ -1549,19 +1549,12 @@ static irqreturn_t tc_irq_handler(int irq, void *arg) + return IRQ_HANDLED; + } + +-static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) ++static int tc_probe_edp_bridge_endpoint(struct tc_data *tc) + { +- struct device *dev = &client->dev; ++ struct device *dev = tc->dev; + struct drm_panel *panel; +- struct tc_data *tc; + int ret; + +- tc = devm_kzalloc(dev, sizeof(*tc), GFP_KERNEL); +- if (!tc) +- return -ENOMEM; +- +- tc->dev = dev; +- + /* port@2 is the output port */ + ret = drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &panel, NULL); + if (ret && ret != -ENODEV) +@@ -1580,6 +1573,25 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) + tc->bridge.type = DRM_MODE_CONNECTOR_DisplayPort; + } + ++ return 0; ++} ++ ++static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) ++{ ++ struct device *dev = &client->dev; ++ struct tc_data *tc; ++ int ret; ++ ++ tc = devm_kzalloc(dev, sizeof(*tc), GFP_KERNEL); ++ if (!tc) ++ return -ENOMEM; ++ ++ tc->dev = dev; ++ ++ ret = tc_probe_edp_bridge_endpoint(tc); ++ if (ret) ++ return ret; ++ + /* Shut down GPIO is optional */ + tc->sd_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH); + if (IS_ERR(tc->sd_gpio)) +diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c +index a8ed66751c2d7..7ee29f0738578 100644 +--- a/drivers/gpu/drm/drm_bridge.c ++++ b/drivers/gpu/drm/drm_bridge.c +@@ -28,6 +28,7 @@ + #include <drm/drm_atomic_state_helper.h> + #include <drm/drm_bridge.h> + #include <drm/drm_encoder.h> ++#include <drm/drm_of.h> + #include <drm/drm_print.h> + + #include "drm_crtc_internal.h" +@@ -51,10 +52,8 @@ + * + * Display drivers are responsible for linking encoders with the first bridge + * in the chains. This is done by acquiring the appropriate bridge with +- * of_drm_find_bridge() or drm_of_find_panel_or_bridge(), or creating it for a +- * panel with drm_panel_bridge_add_typed() (or the managed version +- * devm_drm_panel_bridge_add_typed()). Once acquired, the bridge shall be +- * attached to the encoder with a call to drm_bridge_attach(). ++ * devm_drm_of_get_bridge(). Once acquired, the bridge shall be attached to the ++ * encoder with a call to drm_bridge_attach(). + * + * Bridges are responsible for linking themselves with the next bridge in the + * chain, if any. This is done the same way as for encoders, with the call to +diff --git a/drivers/gpu/drm/drm_dp_aux_bus.c b/drivers/gpu/drm/drm_dp_aux_bus.c +index 298ea7a495913..f7c03ad5a15a5 100644 +--- a/drivers/gpu/drm/drm_dp_aux_bus.c ++++ b/drivers/gpu/drm/drm_dp_aux_bus.c +@@ -66,7 +66,6 @@ static int dp_aux_ep_probe(struct device *dev) + * @dev: The device to remove. + * + * Calls through to the endpoint driver remove. +- * + */ + static void dp_aux_ep_remove(struct device *dev) + { +@@ -120,8 +119,6 @@ ATTRIBUTE_GROUPS(dp_aux_ep_dev); + /** + * dp_aux_ep_dev_release() - Free memory for the dp_aux_ep device + * @dev: The device to free. +- * +- * Return: 0 if no error or negative error code. + */ + static void dp_aux_ep_dev_release(struct device *dev) + { +@@ -256,6 +253,7 @@ int of_dp_aux_populate_ep_devices(struct drm_dp_aux *aux) + + return 0; + } ++EXPORT_SYMBOL_GPL(of_dp_aux_populate_ep_devices); + + static void of_dp_aux_depopulate_ep_devices_void(void *data) + { +diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c +index b3e3babe18c0e..2a586e6489da1 100644 +--- a/drivers/gpu/drm/drm_dp_mst_topology.c ++++ b/drivers/gpu/drm/drm_dp_mst_topology.c +@@ -3860,9 +3860,7 @@ int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr, + if (!mgr->mst_primary) + goto out_fail; + +- ret = drm_dp_dpcd_read(mgr->aux, DP_DPCD_REV, mgr->dpcd, +- DP_RECEIVER_CAP_SIZE); +- if (ret != DP_RECEIVER_CAP_SIZE) { ++ if (drm_dp_read_dpcd_caps(mgr->aux, mgr->dpcd) < 0) { + drm_dbg_kms(mgr->dev, "dpcd read failed - undocked during suspend?\n"); + goto out_fail; + } +@@ -4894,8 +4892,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m, + u8 buf[DP_PAYLOAD_TABLE_SIZE]; + int ret; + +- ret = drm_dp_dpcd_read(mgr->aux, DP_DPCD_REV, buf, DP_RECEIVER_CAP_SIZE); +- if (ret) { ++ if (drm_dp_read_dpcd_caps(mgr->aux, buf) < 0) { + seq_printf(m, "dpcd read failed\n"); + goto out; + } +diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c +index 09c8200458594..6410563a9cb6f 100644 +--- a/drivers/gpu/drm/drm_gem.c ++++ b/drivers/gpu/drm/drm_gem.c +@@ -1224,7 +1224,7 @@ retry: + ret = dma_resv_lock_slow_interruptible(obj->resv, + acquire_ctx); + if (ret) { +- ww_acquire_done(acquire_ctx); ++ ww_acquire_fini(acquire_ctx); + return ret; + } + } +@@ -1249,7 +1249,7 @@ retry: + goto retry; + } + +- ww_acquire_done(acquire_ctx); ++ ww_acquire_fini(acquire_ctx); + return ret; + } + } +diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c +index a61946374c826..a30ffc07470cc 100644 +--- a/drivers/gpu/drm/drm_gem_shmem_helper.c ++++ b/drivers/gpu/drm/drm_gem_shmem_helper.c +@@ -22,17 +22,22 @@ + * + * This library provides helpers for GEM objects backed by shmem buffers + * allocated using anonymous pageable memory. ++ * ++ * Functions that operate on the GEM object receive struct &drm_gem_shmem_object. ++ * For GEM callback helpers in struct &drm_gem_object functions, see likewise ++ * named functions with an _object_ infix (e.g., drm_gem_shmem_object_vmap() wraps ++ * drm_gem_shmem_vmap()). These helpers perform the necessary type conversion. + */ + + static const struct drm_gem_object_funcs drm_gem_shmem_funcs = { +- .free = drm_gem_shmem_free_object, +- .print_info = drm_gem_shmem_print_info, +- .pin = drm_gem_shmem_pin, +- .unpin = drm_gem_shmem_unpin, +- .get_sg_table = drm_gem_shmem_get_sg_table, +- .vmap = drm_gem_shmem_vmap, +- .vunmap = drm_gem_shmem_vunmap, +- .mmap = drm_gem_shmem_mmap, ++ .free = drm_gem_shmem_object_free, ++ .print_info = drm_gem_shmem_object_print_info, ++ .pin = drm_gem_shmem_object_pin, ++ .unpin = drm_gem_shmem_object_unpin, ++ .get_sg_table = drm_gem_shmem_object_get_sg_table, ++ .vmap = drm_gem_shmem_object_vmap, ++ .vunmap = drm_gem_shmem_object_vunmap, ++ .mmap = drm_gem_shmem_object_mmap, + }; + + static struct drm_gem_shmem_object * +@@ -112,16 +117,15 @@ struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t + EXPORT_SYMBOL_GPL(drm_gem_shmem_create); + + /** +- * drm_gem_shmem_free_object - Free resources associated with a shmem GEM object +- * @obj: GEM object to free ++ * drm_gem_shmem_free - Free resources associated with a shmem GEM object ++ * @shmem: shmem GEM object to free + * + * This function cleans up the GEM object state and frees the memory used to +- * store the object itself. It should be used to implement +- * &drm_gem_object_funcs.free. ++ * store the object itself. + */ +-void drm_gem_shmem_free_object(struct drm_gem_object *obj) ++void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem) + { +- struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); ++ struct drm_gem_object *obj = &shmem->base; + + WARN_ON(shmem->vmap_use_count); + +@@ -145,7 +149,7 @@ void drm_gem_shmem_free_object(struct drm_gem_object *obj) + mutex_destroy(&shmem->vmap_lock); + kfree(shmem); + } +-EXPORT_SYMBOL_GPL(drm_gem_shmem_free_object); ++EXPORT_SYMBOL_GPL(drm_gem_shmem_free); + + static int drm_gem_shmem_get_pages_locked(struct drm_gem_shmem_object *shmem) + { +@@ -225,19 +229,16 @@ EXPORT_SYMBOL(drm_gem_shmem_put_pages); + + /** + * drm_gem_shmem_pin - Pin backing pages for a shmem GEM object +- * @obj: GEM object ++ * @shmem: shmem GEM object + * + * This function makes sure the backing pages are pinned in memory while the +- * buffer is exported. It should only be used to implement +- * &drm_gem_object_funcs.pin. ++ * buffer is exported. + * + * Returns: + * 0 on success or a negative error code on failure. + */ +-int drm_gem_shmem_pin(struct drm_gem_object *obj) ++int drm_gem_shmem_pin(struct drm_gem_shmem_object *shmem) + { +- struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); +- + WARN_ON(shmem->base.import_attach); + + return drm_gem_shmem_get_pages(shmem); +@@ -246,15 +247,13 @@ EXPORT_SYMBOL(drm_gem_shmem_pin); + + /** + * drm_gem_shmem_unpin - Unpin backing pages for a shmem GEM object +- * @obj: GEM object ++ * @shmem: shmem GEM object + * + * This function removes the requirement that the backing pages are pinned in +- * memory. It should only be used to implement &drm_gem_object_funcs.unpin. ++ * memory. + */ +-void drm_gem_shmem_unpin(struct drm_gem_object *obj) ++void drm_gem_shmem_unpin(struct drm_gem_shmem_object *shmem) + { +- struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); +- + WARN_ON(shmem->base.import_attach); + + drm_gem_shmem_put_pages(shmem); +@@ -275,6 +274,7 @@ static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem, struct + ret = dma_buf_vmap(obj->import_attach->dmabuf, map); + if (!ret) { + if (WARN_ON(map->is_iomem)) { ++ dma_buf_vunmap(obj->import_attach->dmabuf, map); + ret = -EIO; + goto err_put_pages; + } +@@ -320,20 +320,16 @@ err_zero_use: + * store. + * + * This function makes sure that a contiguous kernel virtual address mapping +- * exists for the buffer backing the shmem GEM object. +- * +- * This function can be used to implement &drm_gem_object_funcs.vmap. But it can +- * also be called by drivers directly, in which case it will hide the +- * differences between dma-buf imported and natively allocated objects. ++ * exists for the buffer backing the shmem GEM object. It hides the differences ++ * between dma-buf imported and natively allocated objects. + * + * Acquired mappings should be cleaned up by calling drm_gem_shmem_vunmap(). + * + * Returns: + * 0 on success or a negative error code on failure. + */ +-int drm_gem_shmem_vmap(struct drm_gem_object *obj, struct dma_buf_map *map) ++int drm_gem_shmem_vmap(struct drm_gem_shmem_object *shmem, struct dma_buf_map *map) + { +- struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); + int ret; + + ret = mutex_lock_interruptible(&shmem->vmap_lock); +@@ -376,21 +372,18 @@ static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem, + * drm_gem_shmem_vmap(). The mapping is only removed when the use count drops to + * zero. + * +- * This function can be used to implement &drm_gem_object_funcs.vmap. But it can +- * also be called by drivers directly, in which case it will hide the +- * differences between dma-buf imported and natively allocated objects. ++ * This function hides the differences between dma-buf imported and natively ++ * allocated objects. + */ +-void drm_gem_shmem_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map) ++void drm_gem_shmem_vunmap(struct drm_gem_shmem_object *shmem, struct dma_buf_map *map) + { +- struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); +- + mutex_lock(&shmem->vmap_lock); + drm_gem_shmem_vunmap_locked(shmem, map); + mutex_unlock(&shmem->vmap_lock); + } + EXPORT_SYMBOL(drm_gem_shmem_vunmap); + +-struct drm_gem_shmem_object * ++static struct drm_gem_shmem_object * + drm_gem_shmem_create_with_handle(struct drm_file *file_priv, + struct drm_device *dev, size_t size, + uint32_t *handle) +@@ -414,15 +407,12 @@ drm_gem_shmem_create_with_handle(struct drm_file *file_priv, + + return shmem; + } +-EXPORT_SYMBOL(drm_gem_shmem_create_with_handle); + + /* Update madvise status, returns true if not purged, else + * false or -errno. + */ +-int drm_gem_shmem_madvise(struct drm_gem_object *obj, int madv) ++int drm_gem_shmem_madvise(struct drm_gem_shmem_object *shmem, int madv) + { +- struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); +- + mutex_lock(&shmem->pages_lock); + + if (shmem->madv >= 0) +@@ -436,14 +426,14 @@ int drm_gem_shmem_madvise(struct drm_gem_object *obj, int madv) + } + EXPORT_SYMBOL(drm_gem_shmem_madvise); + +-void drm_gem_shmem_purge_locked(struct drm_gem_object *obj) ++void drm_gem_shmem_purge_locked(struct drm_gem_shmem_object *shmem) + { ++ struct drm_gem_object *obj = &shmem->base; + struct drm_device *dev = obj->dev; +- struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); + + WARN_ON(!drm_gem_shmem_is_purgeable(shmem)); + +- dma_unmap_sgtable(obj->dev->dev, shmem->sgt, DMA_BIDIRECTIONAL, 0); ++ dma_unmap_sgtable(dev->dev, shmem->sgt, DMA_BIDIRECTIONAL, 0); + sg_free_table(shmem->sgt); + kfree(shmem->sgt); + shmem->sgt = NULL; +@@ -462,18 +452,15 @@ void drm_gem_shmem_purge_locked(struct drm_gem_object *obj) + */ + shmem_truncate_range(file_inode(obj->filp), 0, (loff_t)-1); + +- invalidate_mapping_pages(file_inode(obj->filp)->i_mapping, +- 0, (loff_t)-1); ++ invalidate_mapping_pages(file_inode(obj->filp)->i_mapping, 0, (loff_t)-1); + } + EXPORT_SYMBOL(drm_gem_shmem_purge_locked); + +-bool drm_gem_shmem_purge(struct drm_gem_object *obj) ++bool drm_gem_shmem_purge(struct drm_gem_shmem_object *shmem) + { +- struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); +- + if (!mutex_trylock(&shmem->pages_lock)) + return false; +- drm_gem_shmem_purge_locked(obj); ++ drm_gem_shmem_purge_locked(shmem); + mutex_unlock(&shmem->pages_lock); + + return true; +@@ -581,19 +568,18 @@ static const struct vm_operations_struct drm_gem_shmem_vm_ops = { + + /** + * drm_gem_shmem_mmap - Memory-map a shmem GEM object +- * @obj: gem object ++ * @shmem: shmem GEM object + * @vma: VMA for the area to be mapped + * + * This function implements an augmented version of the GEM DRM file mmap +- * operation for shmem objects. Drivers which employ the shmem helpers should +- * use this function as their &drm_gem_object_funcs.mmap handler. ++ * operation for shmem objects. + * + * Returns: + * 0 on success or a negative error code on failure. + */ +-int drm_gem_shmem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) ++int drm_gem_shmem_mmap(struct drm_gem_shmem_object *shmem, struct vm_area_struct *vma) + { +- struct drm_gem_shmem_object *shmem; ++ struct drm_gem_object *obj = &shmem->base; + int ret; + + if (obj->import_attach) { +@@ -604,8 +590,6 @@ int drm_gem_shmem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) + return dma_buf_mmap(obj->dma_buf, vma, 0); + } + +- shmem = to_drm_gem_shmem_obj(obj); +- + ret = drm_gem_shmem_get_pages(shmem); + if (ret) { + drm_gem_vm_close(vma); +@@ -624,17 +608,13 @@ EXPORT_SYMBOL_GPL(drm_gem_shmem_mmap); + + /** + * drm_gem_shmem_print_info() - Print &drm_gem_shmem_object info for debugfs ++ * @shmem: shmem GEM object + * @p: DRM printer + * @indent: Tab indentation level +- * @obj: GEM object +- * +- * This implements the &drm_gem_object_funcs.info callback. + */ +-void drm_gem_shmem_print_info(struct drm_printer *p, unsigned int indent, +- const struct drm_gem_object *obj) ++void drm_gem_shmem_print_info(const struct drm_gem_shmem_object *shmem, ++ struct drm_printer *p, unsigned int indent) + { +- const struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); +- + drm_printf_indent(p, indent, "pages_use_count=%u\n", shmem->pages_use_count); + drm_printf_indent(p, indent, "vmap_use_count=%u\n", shmem->vmap_use_count); + drm_printf_indent(p, indent, "vaddr=%p\n", shmem->vaddr); +@@ -644,12 +624,10 @@ EXPORT_SYMBOL(drm_gem_shmem_print_info); + /** + * drm_gem_shmem_get_sg_table - Provide a scatter/gather table of pinned + * pages for a shmem GEM object +- * @obj: GEM object ++ * @shmem: shmem GEM object + * + * This function exports a scatter/gather table suitable for PRIME usage by +- * calling the standard DMA mapping API. Drivers should not call this function +- * directly, instead it should only be used as an implementation for +- * &drm_gem_object_funcs.get_sg_table. ++ * calling the standard DMA mapping API. + * + * Drivers who need to acquire an scatter/gather table for objects need to call + * drm_gem_shmem_get_pages_sgt() instead. +@@ -657,9 +635,9 @@ EXPORT_SYMBOL(drm_gem_shmem_print_info); + * Returns: + * A pointer to the scatter/gather table of pinned pages or NULL on failure. + */ +-struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_object *obj) ++struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_shmem_object *shmem) + { +- struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); ++ struct drm_gem_object *obj = &shmem->base; + + WARN_ON(shmem->base.import_attach); + +@@ -670,7 +648,7 @@ EXPORT_SYMBOL_GPL(drm_gem_shmem_get_sg_table); + /** + * drm_gem_shmem_get_pages_sgt - Pin pages, dma map them, and return a + * scatter/gather table for a shmem GEM object. +- * @obj: GEM object ++ * @shmem: shmem GEM object + * + * This function returns a scatter/gather table suitable for driver usage. If + * the sg table doesn't exist, the pages are pinned, dma-mapped, and a sg +@@ -683,10 +661,10 @@ EXPORT_SYMBOL_GPL(drm_gem_shmem_get_sg_table); + * Returns: + * A pointer to the scatter/gather table of pinned pages or errno on failure. + */ +-struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_object *obj) ++struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_shmem_object *shmem) + { ++ struct drm_gem_object *obj = &shmem->base; + int ret; +- struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); + struct sg_table *sgt; + + if (shmem->sgt) +@@ -698,7 +676,7 @@ struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_object *obj) + if (ret) + return ERR_PTR(ret); + +- sgt = drm_gem_shmem_get_sg_table(&shmem->base); ++ sgt = drm_gem_shmem_get_sg_table(shmem); + if (IS_ERR(sgt)) { + ret = PTR_ERR(sgt); + goto err_put_pages; +diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c +index 71b646c4131fc..00d470ff071d3 100644 +--- a/drivers/gpu/drm/drm_mipi_dbi.c ++++ b/drivers/gpu/drm/drm_mipi_dbi.c +@@ -1183,6 +1183,13 @@ int mipi_dbi_spi_transfer(struct spi_device *spi, u32 speed_hz, + size_t chunk; + int ret; + ++ /* In __spi_validate, there's a validation that no partial transfers ++ * are accepted (xfer->len % w_size must be zero). ++ * Here we align max_chunk to multiple of 2 (16bits), ++ * to prevent transfers from being rejected. ++ */ ++ max_chunk = ALIGN_DOWN(max_chunk, 2); ++ + spi_message_init_with_transfers(&m, &tr, 1); + + while (len) { +diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c +index 997b8827fed27..37c34146eea83 100644 +--- a/drivers/gpu/drm/drm_of.c ++++ b/drivers/gpu/drm/drm_of.c +@@ -231,6 +231,9 @@ EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint); + * return either the associated struct drm_panel or drm_bridge device. Either + * @panel or @bridge must not be NULL. + * ++ * This function is deprecated and should not be used in new drivers. Use ++ * devm_drm_of_get_bridge() instead. ++ * + * Returns zero if successful, or one of the standard error codes if it fails. + */ + int drm_of_find_panel_or_bridge(const struct device_node *np, +diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c +index 12571ac455404..12989a47eb66e 100644 +--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c ++++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c +@@ -806,31 +806,40 @@ static int exynos7_decon_resume(struct device *dev) + if (ret < 0) { + DRM_DEV_ERROR(dev, "Failed to prepare_enable the pclk [%d]\n", + ret); +- return ret; ++ goto err_pclk_enable; + } + + ret = clk_prepare_enable(ctx->aclk); + if (ret < 0) { + DRM_DEV_ERROR(dev, "Failed to prepare_enable the aclk [%d]\n", + ret); +- return ret; ++ goto err_aclk_enable; + } + + ret = clk_prepare_enable(ctx->eclk); + if (ret < 0) { + DRM_DEV_ERROR(dev, "Failed to prepare_enable the eclk [%d]\n", + ret); +- return ret; ++ goto err_eclk_enable; + } + + ret = clk_prepare_enable(ctx->vclk); + if (ret < 0) { + DRM_DEV_ERROR(dev, "Failed to prepare_enable the vclk [%d]\n", + ret); +- return ret; ++ goto err_vclk_enable; + } + + return 0; ++ ++err_vclk_enable: ++ clk_disable_unprepare(ctx->eclk); ++err_eclk_enable: ++ clk_disable_unprepare(ctx->aclk); ++err_aclk_enable: ++ clk_disable_unprepare(ctx->pclk); ++err_pclk_enable: ++ return ret; + } + #endif + +diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c +index 8c97a20dfe231..22bebeb9c3ac0 100644 +--- a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c ++++ b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c +@@ -7,9 +7,11 @@ + + #include <drm/drm_damage_helper.h> + #include <drm/drm_drv.h> ++#include <drm/drm_edid.h> + #include <drm/drm_fb_helper.h> + #include <drm/drm_format_helper.h> + #include <drm/drm_fourcc.h> ++#include <drm/drm_framebuffer.h> + #include <drm/drm_gem_atomic_helper.h> + #include <drm/drm_gem_framebuffer_helper.h> + #include <drm/drm_gem_shmem_helper.h> +diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c +index de62966243cd5..09ea621a4806c 100644 +--- a/drivers/gpu/drm/lima/lima_gem.c ++++ b/drivers/gpu/drm/lima/lima_gem.c +@@ -127,7 +127,7 @@ int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file, + if (err) + goto out; + } else { +- struct sg_table *sgt = drm_gem_shmem_get_pages_sgt(obj); ++ struct sg_table *sgt = drm_gem_shmem_get_pages_sgt(shmem); + + if (IS_ERR(sgt)) { + err = PTR_ERR(sgt); +@@ -151,7 +151,7 @@ static void lima_gem_free_object(struct drm_gem_object *obj) + if (!list_empty(&bo->va)) + dev_err(obj->dev->dev, "lima gem free bo still has va\n"); + +- drm_gem_shmem_free_object(obj); ++ drm_gem_shmem_free(&bo->base); + } + + static int lima_gem_object_open(struct drm_gem_object *obj, struct drm_file *file) +@@ -179,7 +179,7 @@ static int lima_gem_pin(struct drm_gem_object *obj) + if (bo->heap_size) + return -EINVAL; + +- return drm_gem_shmem_pin(obj); ++ return drm_gem_shmem_pin(&bo->base); + } + + static int lima_gem_vmap(struct drm_gem_object *obj, struct dma_buf_map *map) +@@ -189,7 +189,7 @@ static int lima_gem_vmap(struct drm_gem_object *obj, struct dma_buf_map *map) + if (bo->heap_size) + return -EINVAL; + +- return drm_gem_shmem_vmap(obj, map); ++ return drm_gem_shmem_vmap(&bo->base, map); + } + + static int lima_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +@@ -199,19 +199,19 @@ static int lima_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) + if (bo->heap_size) + return -EINVAL; + +- return drm_gem_shmem_mmap(obj, vma); ++ return drm_gem_shmem_mmap(&bo->base, vma); + } + + static const struct drm_gem_object_funcs lima_gem_funcs = { + .free = lima_gem_free_object, + .open = lima_gem_object_open, + .close = lima_gem_object_close, +- .print_info = drm_gem_shmem_print_info, ++ .print_info = drm_gem_shmem_object_print_info, + .pin = lima_gem_pin, +- .unpin = drm_gem_shmem_unpin, +- .get_sg_table = drm_gem_shmem_get_sg_table, ++ .unpin = drm_gem_shmem_object_unpin, ++ .get_sg_table = drm_gem_shmem_object_get_sg_table, + .vmap = lima_gem_vmap, +- .vunmap = drm_gem_shmem_vunmap, ++ .vunmap = drm_gem_shmem_object_vunmap, + .mmap = lima_gem_mmap, + }; + +diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c +index dba8329937a32..2e817dbdcad75 100644 +--- a/drivers/gpu/drm/lima/lima_sched.c ++++ b/drivers/gpu/drm/lima/lima_sched.c +@@ -390,7 +390,7 @@ static void lima_sched_build_error_task_list(struct lima_sched_task *task) + } else { + buffer_chunk->size = lima_bo_size(bo); + +- ret = drm_gem_shmem_vmap(&bo->base.base, &map); ++ ret = drm_gem_shmem_vmap(&bo->base, &map); + if (ret) { + kvfree(et); + goto out; +@@ -398,7 +398,7 @@ static void lima_sched_build_error_task_list(struct lima_sched_task *task) + + memcpy(buffer_chunk + 1, map.vaddr, buffer_chunk->size); + +- drm_gem_shmem_vunmap(&bo->base.base, &map); ++ drm_gem_shmem_vunmap(&bo->base, &map); + } + + buffer_chunk = (void *)(buffer_chunk + 1) + buffer_chunk->size; +diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c +index 180ebbccbedaf..0b58d7f4ba780 100644 +--- a/drivers/gpu/drm/mcde/mcde_dsi.c ++++ b/drivers/gpu/drm/mcde/mcde_dsi.c +@@ -1111,6 +1111,7 @@ static int mcde_dsi_bind(struct device *dev, struct device *master, + bridge = of_drm_find_bridge(child); + if (!bridge) { + dev_err(dev, "failed to find bridge\n"); ++ of_node_put(child); + return -EINVAL; + } + } +diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c +index e61cd67b978ff..41c783349321e 100644 +--- a/drivers/gpu/drm/mediatek/mtk_dpi.c ++++ b/drivers/gpu/drm/mediatek/mtk_dpi.c +@@ -54,13 +54,7 @@ enum mtk_dpi_out_channel_swap { + }; + + enum mtk_dpi_out_color_format { +- MTK_DPI_COLOR_FORMAT_RGB, +- MTK_DPI_COLOR_FORMAT_RGB_FULL, +- MTK_DPI_COLOR_FORMAT_YCBCR_444, +- MTK_DPI_COLOR_FORMAT_YCBCR_422, +- MTK_DPI_COLOR_FORMAT_XV_YCC, +- MTK_DPI_COLOR_FORMAT_YCBCR_444_FULL, +- MTK_DPI_COLOR_FORMAT_YCBCR_422_FULL ++ MTK_DPI_COLOR_FORMAT_RGB + }; + + struct mtk_dpi { +@@ -364,24 +358,11 @@ static void mtk_dpi_config_disable_edge(struct mtk_dpi *dpi) + static void mtk_dpi_config_color_format(struct mtk_dpi *dpi, + enum mtk_dpi_out_color_format format) + { +- if ((format == MTK_DPI_COLOR_FORMAT_YCBCR_444) || +- (format == MTK_DPI_COLOR_FORMAT_YCBCR_444_FULL)) { +- mtk_dpi_config_yuv422_enable(dpi, false); +- mtk_dpi_config_csc_enable(dpi, true); +- mtk_dpi_config_swap_input(dpi, false); +- mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_BGR); +- } else if ((format == MTK_DPI_COLOR_FORMAT_YCBCR_422) || +- (format == MTK_DPI_COLOR_FORMAT_YCBCR_422_FULL)) { +- mtk_dpi_config_yuv422_enable(dpi, true); +- mtk_dpi_config_csc_enable(dpi, true); +- mtk_dpi_config_swap_input(dpi, true); +- mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_RGB); +- } else { +- mtk_dpi_config_yuv422_enable(dpi, false); +- mtk_dpi_config_csc_enable(dpi, false); +- mtk_dpi_config_swap_input(dpi, false); +- mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_RGB); +- } ++ /* only support RGB888 */ ++ mtk_dpi_config_yuv422_enable(dpi, false); ++ mtk_dpi_config_csc_enable(dpi, false); ++ mtk_dpi_config_swap_input(dpi, false); ++ mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_RGB); + } + + static void mtk_dpi_dual_edge(struct mtk_dpi *dpi) +@@ -436,7 +417,6 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi) + if (dpi->pinctrl && dpi->pins_dpi) + pinctrl_select_state(dpi->pinctrl, dpi->pins_dpi); + +- mtk_dpi_enable(dpi); + return 0; + + err_pixel: +@@ -658,6 +638,7 @@ static void mtk_dpi_bridge_enable(struct drm_bridge *bridge) + + mtk_dpi_power_on(dpi); + mtk_dpi_set_display_mode(dpi, &dpi->mode); ++ mtk_dpi_enable(dpi); + } + + static enum drm_mode_status +diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c +index 5d90d2eb00193..ac14e598a14f7 100644 +--- a/drivers/gpu/drm/mediatek/mtk_dsi.c ++++ b/drivers/gpu/drm/mediatek/mtk_dsi.c +@@ -203,6 +203,7 @@ struct mtk_dsi { + struct mtk_phy_timing phy_timing; + int refcount; + bool enabled; ++ bool lanes_ready; + u32 irq_data; + wait_queue_head_t irq_wait_queue; + const struct mtk_dsi_driver_data *driver_data; +@@ -649,18 +650,11 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi) + mtk_dsi_reset_engine(dsi); + mtk_dsi_phy_timconfig(dsi); + +- mtk_dsi_rxtx_control(dsi); +- usleep_range(30, 100); +- mtk_dsi_reset_dphy(dsi); + mtk_dsi_ps_control_vact(dsi); + mtk_dsi_set_vm_cmd(dsi); + mtk_dsi_config_vdo_timing(dsi); + mtk_dsi_set_interrupt_enable(dsi); + +- mtk_dsi_clk_ulp_mode_leave(dsi); +- mtk_dsi_lane0_ulp_mode_leave(dsi); +- mtk_dsi_clk_hs_mode(dsi, 0); +- + return 0; + err_disable_engine_clk: + clk_disable_unprepare(dsi->engine_clk); +@@ -679,19 +673,11 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi) + if (--dsi->refcount != 0) + return; + +- /* +- * mtk_dsi_stop() and mtk_dsi_start() is asymmetric, since +- * mtk_dsi_stop() should be called after mtk_drm_crtc_atomic_disable(), +- * which needs irq for vblank, and mtk_dsi_stop() will disable irq. +- * mtk_dsi_start() needs to be called in mtk_output_dsi_enable(), +- * after dsi is fully set. +- */ +- mtk_dsi_stop(dsi); +- +- mtk_dsi_switch_to_cmd_mode(dsi, VM_DONE_INT_FLAG, 500); + mtk_dsi_reset_engine(dsi); + mtk_dsi_lane0_ulp_mode_enter(dsi); + mtk_dsi_clk_ulp_mode_enter(dsi); ++ /* set the lane number as 0 to pull down mipi */ ++ writel(0, dsi->regs + DSI_TXRX_CTRL); + + mtk_dsi_disable(dsi); + +@@ -699,21 +685,31 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi) + clk_disable_unprepare(dsi->digital_clk); + + phy_power_off(dsi->phy); ++ ++ dsi->lanes_ready = false; + } + +-static void mtk_output_dsi_enable(struct mtk_dsi *dsi) ++static void mtk_dsi_lane_ready(struct mtk_dsi *dsi) + { +- int ret; ++ if (!dsi->lanes_ready) { ++ dsi->lanes_ready = true; ++ mtk_dsi_rxtx_control(dsi); ++ usleep_range(30, 100); ++ mtk_dsi_reset_dphy(dsi); ++ mtk_dsi_clk_ulp_mode_leave(dsi); ++ mtk_dsi_lane0_ulp_mode_leave(dsi); ++ mtk_dsi_clk_hs_mode(dsi, 0); ++ msleep(20); ++ /* The reaction time after pulling up the mipi signal for dsi_rx */ ++ } ++} + ++static void mtk_output_dsi_enable(struct mtk_dsi *dsi) ++{ + if (dsi->enabled) + return; + +- ret = mtk_dsi_poweron(dsi); +- if (ret < 0) { +- DRM_ERROR("failed to power on dsi\n"); +- return; +- } +- ++ mtk_dsi_lane_ready(dsi); + mtk_dsi_set_mode(dsi); + mtk_dsi_clk_hs_mode(dsi, 1); + +@@ -727,7 +723,16 @@ static void mtk_output_dsi_disable(struct mtk_dsi *dsi) + if (!dsi->enabled) + return; + +- mtk_dsi_poweroff(dsi); ++ /* ++ * mtk_dsi_stop() and mtk_dsi_start() is asymmetric, since ++ * mtk_dsi_stop() should be called after mtk_drm_crtc_atomic_disable(), ++ * which needs irq for vblank, and mtk_dsi_stop() will disable irq. ++ * mtk_dsi_start() needs to be called in mtk_output_dsi_enable(), ++ * after dsi is fully set. ++ */ ++ mtk_dsi_stop(dsi); ++ ++ mtk_dsi_switch_to_cmd_mode(dsi, VM_DONE_INT_FLAG, 500); + + dsi->enabled = false; + } +@@ -751,24 +756,50 @@ static void mtk_dsi_bridge_mode_set(struct drm_bridge *bridge, + drm_display_mode_to_videomode(adjusted, &dsi->vm); + } + +-static void mtk_dsi_bridge_disable(struct drm_bridge *bridge) ++static void mtk_dsi_bridge_atomic_disable(struct drm_bridge *bridge, ++ struct drm_bridge_state *old_bridge_state) + { + struct mtk_dsi *dsi = bridge_to_dsi(bridge); + + mtk_output_dsi_disable(dsi); + } + +-static void mtk_dsi_bridge_enable(struct drm_bridge *bridge) ++static void mtk_dsi_bridge_atomic_enable(struct drm_bridge *bridge, ++ struct drm_bridge_state *old_bridge_state) + { + struct mtk_dsi *dsi = bridge_to_dsi(bridge); + ++ if (dsi->refcount == 0) ++ return; ++ + mtk_output_dsi_enable(dsi); + } + ++static void mtk_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge, ++ struct drm_bridge_state *old_bridge_state) ++{ ++ struct mtk_dsi *dsi = bridge_to_dsi(bridge); ++ int ret; ++ ++ ret = mtk_dsi_poweron(dsi); ++ if (ret < 0) ++ DRM_ERROR("failed to power on dsi\n"); ++} ++ ++static void mtk_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge, ++ struct drm_bridge_state *old_bridge_state) ++{ ++ struct mtk_dsi *dsi = bridge_to_dsi(bridge); ++ ++ mtk_dsi_poweroff(dsi); ++} ++ + static const struct drm_bridge_funcs mtk_dsi_bridge_funcs = { + .attach = mtk_dsi_bridge_attach, +- .disable = mtk_dsi_bridge_disable, +- .enable = mtk_dsi_bridge_enable, ++ .atomic_disable = mtk_dsi_bridge_atomic_disable, ++ .atomic_enable = mtk_dsi_bridge_atomic_enable, ++ .atomic_pre_enable = mtk_dsi_bridge_atomic_pre_enable, ++ .atomic_post_disable = mtk_dsi_bridge_atomic_post_disable, + .mode_set = mtk_dsi_bridge_mode_set, + }; + +@@ -891,24 +922,35 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host, + u8 read_data[16]; + void *src_addr; + u8 irq_flag = CMD_DONE_INT_FLAG; ++ u32 dsi_mode; ++ int ret; + +- if (readl(dsi->regs + DSI_MODE_CTRL) & MODE) { +- DRM_ERROR("dsi engine is not command mode\n"); +- return -EINVAL; ++ dsi_mode = readl(dsi->regs + DSI_MODE_CTRL); ++ if (dsi_mode & MODE) { ++ mtk_dsi_stop(dsi); ++ ret = mtk_dsi_switch_to_cmd_mode(dsi, VM_DONE_INT_FLAG, 500); ++ if (ret) ++ goto restore_dsi_mode; + } + + if (MTK_DSI_HOST_IS_READ(msg->type)) + irq_flag |= LPRX_RD_RDY_INT_FLAG; + +- if (mtk_dsi_host_send_cmd(dsi, msg, irq_flag) < 0) +- return -ETIME; ++ mtk_dsi_lane_ready(dsi); + +- if (!MTK_DSI_HOST_IS_READ(msg->type)) +- return 0; ++ ret = mtk_dsi_host_send_cmd(dsi, msg, irq_flag); ++ if (ret) ++ goto restore_dsi_mode; ++ ++ if (!MTK_DSI_HOST_IS_READ(msg->type)) { ++ recv_cnt = 0; ++ goto restore_dsi_mode; ++ } + + if (!msg->rx_buf) { + DRM_ERROR("dsi receive buffer size may be NULL\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto restore_dsi_mode; + } + + for (i = 0; i < 16; i++) +@@ -933,7 +975,13 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host, + DRM_INFO("dsi get %d byte data from the panel address(0x%x)\n", + recv_cnt, *((u8 *)(msg->tx_buf))); + +- return recv_cnt; ++restore_dsi_mode: ++ if (dsi_mode & MODE) { ++ mtk_dsi_set_mode(dsi); ++ mtk_dsi_start(dsi); ++ } ++ ++ return ret < 0 ? ret : recv_cnt; + } + + static const struct mipi_dsi_host_ops mtk_dsi_ops = { +diff --git a/drivers/gpu/drm/meson/Kconfig b/drivers/gpu/drm/meson/Kconfig +index 9f9281dd49f84..a4e1ed96e5e8b 100644 +--- a/drivers/gpu/drm/meson/Kconfig ++++ b/drivers/gpu/drm/meson/Kconfig +@@ -6,9 +6,11 @@ config DRM_MESON + select DRM_KMS_HELPER + select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER ++ select DRM_DISPLAY_CONNECTOR + select VIDEOMODE_HELPERS + select REGMAP_MMIO + select MESON_CANVAS ++ select CEC_CORE if CEC_NOTIFIER + + config DRM_MESON_DW_HDMI + tristate "HDMI Synopsys Controller support for Amlogic Meson Display" +diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c +index fb540a503efed..5cd2b2ebbbd33 100644 +--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c ++++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c +@@ -803,6 +803,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master, + dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709; + dw_plat_data->ycbcr_420_allowed = true; + dw_plat_data->disable_cec = true; ++ dw_plat_data->output_port = 1; + + if (dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxl-dw-hdmi") || + dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxm-dw-hdmi") || +diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c +index db332fa4cd548..a7692584487cc 100644 +--- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c ++++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c +@@ -14,8 +14,11 @@ + #include <linux/regulator/consumer.h> + #include <linux/reset.h> + ++#include <media/cec-notifier.h> ++ + #include <drm/drm_atomic_helper.h> + #include <drm/drm_bridge.h> ++#include <drm/drm_bridge_connector.h> + #include <drm/drm_device.h> + #include <drm/drm_edid.h> + #include <drm/drm_probe_helper.h> +@@ -34,8 +37,10 @@ struct meson_encoder_hdmi { + struct drm_encoder encoder; + struct drm_bridge bridge; + struct drm_bridge *next_bridge; ++ struct drm_connector *connector; + struct meson_drm *priv; + unsigned long output_bus_fmt; ++ struct cec_notifier *cec_notifier; + }; + + #define bridge_to_meson_encoder_hdmi(x) \ +@@ -50,6 +55,14 @@ static int meson_encoder_hdmi_attach(struct drm_bridge *bridge, + &encoder_hdmi->bridge, flags); + } + ++static void meson_encoder_hdmi_detach(struct drm_bridge *bridge) ++{ ++ struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge); ++ ++ cec_notifier_conn_unregister(encoder_hdmi->cec_notifier); ++ encoder_hdmi->cec_notifier = NULL; ++} ++ + static void meson_encoder_hdmi_set_vclk(struct meson_encoder_hdmi *encoder_hdmi, + const struct drm_display_mode *mode) + { +@@ -298,9 +311,30 @@ static int meson_encoder_hdmi_atomic_check(struct drm_bridge *bridge, + return 0; + } + ++static void meson_encoder_hdmi_hpd_notify(struct drm_bridge *bridge, ++ enum drm_connector_status status) ++{ ++ struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge); ++ struct edid *edid; ++ ++ if (!encoder_hdmi->cec_notifier) ++ return; ++ ++ if (status == connector_status_connected) { ++ edid = drm_bridge_get_edid(encoder_hdmi->next_bridge, encoder_hdmi->connector); ++ if (!edid) ++ return; ++ ++ cec_notifier_set_phys_addr_from_edid(encoder_hdmi->cec_notifier, edid); ++ } else ++ cec_notifier_phys_addr_invalidate(encoder_hdmi->cec_notifier); ++} ++ + static const struct drm_bridge_funcs meson_encoder_hdmi_bridge_funcs = { + .attach = meson_encoder_hdmi_attach, ++ .detach = meson_encoder_hdmi_detach, + .mode_valid = meson_encoder_hdmi_mode_valid, ++ .hpd_notify = meson_encoder_hdmi_hpd_notify, + .atomic_enable = meson_encoder_hdmi_atomic_enable, + .atomic_disable = meson_encoder_hdmi_atomic_disable, + .atomic_get_input_bus_fmts = meson_encoder_hdmi_get_inp_bus_fmts, +@@ -313,6 +347,7 @@ static const struct drm_bridge_funcs meson_encoder_hdmi_bridge_funcs = { + int meson_encoder_hdmi_init(struct meson_drm *priv) + { + struct meson_encoder_hdmi *meson_encoder_hdmi; ++ struct platform_device *pdev; + struct device_node *remote; + int ret; + +@@ -330,13 +365,15 @@ int meson_encoder_hdmi_init(struct meson_drm *priv) + meson_encoder_hdmi->next_bridge = of_drm_find_bridge(remote); + if (!meson_encoder_hdmi->next_bridge) { + dev_err(priv->dev, "Failed to find HDMI transceiver bridge\n"); +- return -EPROBE_DEFER; ++ ret = -EPROBE_DEFER; ++ goto err_put_node; + } + + /* HDMI Encoder Bridge */ + meson_encoder_hdmi->bridge.funcs = &meson_encoder_hdmi_bridge_funcs; + meson_encoder_hdmi->bridge.of_node = priv->dev->of_node; + meson_encoder_hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA; ++ meson_encoder_hdmi->bridge.interlace_allowed = true; + + drm_bridge_add(&meson_encoder_hdmi->bridge); + +@@ -347,24 +384,73 @@ int meson_encoder_hdmi_init(struct meson_drm *priv) + DRM_MODE_ENCODER_TMDS); + if (ret) { + dev_err(priv->dev, "Failed to init HDMI encoder: %d\n", ret); +- return ret; ++ goto err_put_node; + } + + meson_encoder_hdmi->encoder.possible_crtcs = BIT(0); + + /* Attach HDMI Encoder Bridge to Encoder */ +- ret = drm_bridge_attach(&meson_encoder_hdmi->encoder, &meson_encoder_hdmi->bridge, NULL, 0); ++ ret = drm_bridge_attach(&meson_encoder_hdmi->encoder, &meson_encoder_hdmi->bridge, NULL, ++ DRM_BRIDGE_ATTACH_NO_CONNECTOR); + if (ret) { + dev_err(priv->dev, "Failed to attach bridge: %d\n", ret); +- return ret; ++ goto err_put_node; + } + ++ /* Initialize & attach Bridge Connector */ ++ meson_encoder_hdmi->connector = drm_bridge_connector_init(priv->drm, ++ &meson_encoder_hdmi->encoder); ++ if (IS_ERR(meson_encoder_hdmi->connector)) { ++ dev_err(priv->dev, "Unable to create HDMI bridge connector\n"); ++ ret = PTR_ERR(meson_encoder_hdmi->connector); ++ goto err_put_node; ++ } ++ drm_connector_attach_encoder(meson_encoder_hdmi->connector, ++ &meson_encoder_hdmi->encoder); ++ + /* + * We should have now in place: +- * encoder->[hdmi encoder bridge]->[dw-hdmi bridge]->[dw-hdmi connector] ++ * encoder->[hdmi encoder bridge]->[dw-hdmi bridge]->[display connector bridge]->[display connector] ++ */ ++ ++ /* ++ * drm_connector_attach_max_bpc_property() requires the ++ * connector to have a state. + */ ++ drm_atomic_helper_connector_reset(meson_encoder_hdmi->connector); ++ ++ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL) || ++ meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) || ++ meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) ++ drm_connector_attach_hdr_output_metadata_property(meson_encoder_hdmi->connector); ++ ++ drm_connector_attach_max_bpc_property(meson_encoder_hdmi->connector, 8, 8); ++ ++ /* Handle this here until handled by drm_bridge_connector_init() */ ++ meson_encoder_hdmi->connector->ycbcr_420_allowed = true; ++ ++ pdev = of_find_device_by_node(remote); ++ of_node_put(remote); ++ if (pdev) { ++ struct cec_connector_info conn_info; ++ struct cec_notifier *notifier; ++ ++ cec_fill_conn_info_from_drm(&conn_info, meson_encoder_hdmi->connector); ++ ++ notifier = cec_notifier_conn_register(&pdev->dev, NULL, &conn_info); ++ if (!notifier) { ++ put_device(&pdev->dev); ++ return -ENOMEM; ++ } ++ ++ meson_encoder_hdmi->cec_notifier = notifier; ++ } + + dev_dbg(priv->dev, "HDMI encoder initialized\n"); + + return 0; ++ ++err_put_node: ++ of_node_put(remote); ++ return ret; + } +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +index 768012243b440..2186fc947e5b5 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +@@ -230,6 +230,9 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, + if (!state) + continue; + ++ if (!state->visible) ++ continue; ++ + pstate = to_dpu_plane_state(state); + fb = state->fb; + +@@ -898,6 +901,20 @@ struct plane_state { + u32 pipe_id; + }; + ++static bool dpu_crtc_needs_dirtyfb(struct drm_crtc_state *cstate) ++{ ++ struct drm_crtc *crtc = cstate->crtc; ++ struct drm_encoder *encoder; ++ ++ drm_for_each_encoder_mask (encoder, crtc->dev, cstate->encoder_mask) { ++ if (dpu_encoder_get_intf_mode(encoder) == INTF_MODE_CMD) { ++ return true; ++ } ++ } ++ ++ return false; ++} ++ + static int dpu_crtc_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_state *state) + { +@@ -918,6 +935,7 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, + const struct drm_plane_state *pipe_staged[SSPP_MAX]; + int left_zpos_cnt = 0, right_zpos_cnt = 0; + struct drm_rect crtc_rect = { 0 }; ++ bool needs_dirtyfb = dpu_crtc_needs_dirtyfb(crtc_state); + + pstates = kzalloc(sizeof(*pstates) * DPU_STAGE_MAX * 4, GFP_KERNEL); + +@@ -949,6 +967,7 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, + + /* get plane state for all drm planes associated with crtc state */ + drm_atomic_crtc_state_for_each_plane_state(plane, pstate, crtc_state) { ++ struct dpu_plane_state *dpu_pstate = to_dpu_plane_state(pstate); + struct drm_rect dst, clip = crtc_rect; + + if (IS_ERR_OR_NULL(pstate)) { +@@ -960,11 +979,16 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, + if (cnt >= DPU_STAGE_MAX * 4) + continue; + +- pstates[cnt].dpu_pstate = to_dpu_plane_state(pstate); ++ if (!pstate->visible) ++ continue; ++ ++ pstates[cnt].dpu_pstate = dpu_pstate; + pstates[cnt].drm_pstate = pstate; + pstates[cnt].stage = pstate->normalized_zpos; + pstates[cnt].pipe_id = dpu_plane_pipe(plane); + ++ dpu_pstate->needs_dirtyfb = needs_dirtyfb; ++ + if (pipe_staged[pstates[cnt].pipe_id]) { + multirect_plane[multirect_count].r0 = + pipe_staged[pstates[cnt].pipe_id]; +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +index c989621209aa7..e32fe89c203cd 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +@@ -894,7 +894,7 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane, + + if (pstate->aspace) { + ret = msm_framebuffer_prepare(new_state->fb, +- pstate->aspace); ++ pstate->aspace, pstate->needs_dirtyfb); + if (ret) { + DPU_ERROR("failed to prepare framebuffer\n"); + return ret; +@@ -925,7 +925,8 @@ static void dpu_plane_cleanup_fb(struct drm_plane *plane, + + DPU_DEBUG_PLANE(pdpu, "FB[%u]\n", old_state->fb->base.id); + +- msm_framebuffer_cleanup(old_state->fb, old_pstate->aspace); ++ msm_framebuffer_cleanup(old_state->fb, old_pstate->aspace, ++ old_pstate->needs_dirtyfb); + } + + static bool dpu_plane_validate_src(struct drm_rect *src, +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h +index 34e03ac05f4a8..17ff48564c8a7 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h +@@ -28,6 +28,7 @@ + * @cdp_cfg: CDP configuration + * @plane_fetch_bw: calculated BW per plane + * @plane_clk: calculated clk per plane ++ * @needs_dirtyfb: whether attached CRTC needs pixel data explicitly flushed + */ + struct dpu_plane_state { + struct drm_plane_state base; +@@ -45,6 +46,8 @@ struct dpu_plane_state { + struct dpu_hw_pipe_cdp_cfg cdp_cfg; + u64 plane_fetch_bw; + u64 plane_clk; ++ ++ bool needs_dirtyfb; + }; + + /** +diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c +index 49bdabea8ed59..3e20f72d75efd 100644 +--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c ++++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c +@@ -7,6 +7,7 @@ + #include <drm/drm_atomic.h> + #include <drm/drm_damage_helper.h> + #include <drm/drm_fourcc.h> ++#include <drm/drm_gem_atomic_helper.h> + + #include "mdp4_kms.h" + +@@ -90,6 +91,20 @@ static const struct drm_plane_funcs mdp4_plane_funcs = { + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, + }; + ++static int mdp4_plane_prepare_fb(struct drm_plane *plane, ++ struct drm_plane_state *new_state) ++{ ++ struct msm_drm_private *priv = plane->dev->dev_private; ++ struct msm_kms *kms = priv->kms; ++ ++ if (!new_state->fb) ++ return 0; ++ ++ drm_gem_plane_helper_prepare_fb(plane, new_state); ++ ++ return msm_framebuffer_prepare(new_state->fb, kms->aspace, false); ++} ++ + static void mdp4_plane_cleanup_fb(struct drm_plane *plane, + struct drm_plane_state *old_state) + { +@@ -102,7 +117,7 @@ static void mdp4_plane_cleanup_fb(struct drm_plane *plane, + return; + + DBG("%s: cleanup: FB[%u]", mdp4_plane->name, fb->base.id); +- msm_framebuffer_cleanup(fb, kms->aspace); ++ msm_framebuffer_cleanup(fb, kms->aspace, false); + } + + +@@ -130,7 +145,7 @@ static void mdp4_plane_atomic_update(struct drm_plane *plane, + } + + static const struct drm_plane_helper_funcs mdp4_plane_helper_funcs = { +- .prepare_fb = msm_atomic_prepare_fb, ++ .prepare_fb = mdp4_plane_prepare_fb, + .cleanup_fb = mdp4_plane_cleanup_fb, + .atomic_check = mdp4_plane_atomic_check, + .atomic_update = mdp4_plane_atomic_update, +diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +index 0e02e252ff894..31447da0af25c 100644 +--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c ++++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +@@ -696,6 +696,8 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, + { + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, + crtc); ++ struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc_state); ++ struct mdp5_interface *intf = mdp5_cstate->pipeline.intf; + struct mdp5_kms *mdp5_kms = get_kms(crtc); + struct drm_plane *plane; + struct drm_device *dev = crtc->dev; +@@ -712,12 +714,18 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, + DBG("%s: check", crtc->name); + + drm_atomic_crtc_state_for_each_plane_state(plane, pstate, crtc_state) { ++ struct mdp5_plane_state *mdp5_pstate = ++ to_mdp5_plane_state(pstate); ++ + if (!pstate->visible) + continue; + + pstates[cnt].plane = plane; + pstates[cnt].state = to_mdp5_plane_state(pstate); + ++ mdp5_pstate->needs_dirtyfb = ++ intf->mode == MDP5_INTF_DSI_MODE_COMMAND; ++ + /* + * if any plane on this crtc uses 2 hwpipes, then we need + * the crtc to have a right hwmixer. +diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h +index ac269a6802df2..29bf11f086011 100644 +--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h ++++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h +@@ -100,6 +100,11 @@ struct mdp5_plane_state { + + /* assigned by crtc blender */ + enum mdp_mixer_stage_id stage; ++ ++ /* whether attached CRTC needs pixel data explicitly flushed to ++ * display (ex. DSI command mode display) ++ */ ++ bool needs_dirtyfb; + }; + #define to_mdp5_plane_state(x) \ + container_of(x, struct mdp5_plane_state, base) +diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c +index a4f5cb90f3e80..e4b8a789835a4 100644 +--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c ++++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c +@@ -123,12 +123,13 @@ int mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe) + { + struct msm_drm_private *priv = s->dev->dev_private; + struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms)); +- struct mdp5_global_state *state = mdp5_get_global_state(s); ++ struct mdp5_global_state *state; + struct mdp5_hw_pipe_state *new_state; + + if (!hwpipe) + return 0; + ++ state = mdp5_get_global_state(s); + if (IS_ERR(state)) + return PTR_ERR(state); + +diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c +index c0d947bce9e9a..9c42776cb9a8a 100644 +--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c ++++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c +@@ -8,6 +8,7 @@ + #include <drm/drm_atomic.h> + #include <drm/drm_damage_helper.h> + #include <drm/drm_fourcc.h> ++#include <drm/drm_gem_atomic_helper.h> + #include <drm/drm_print.h> + + #include "mdp5_kms.h" +@@ -143,18 +144,34 @@ static const struct drm_plane_funcs mdp5_plane_funcs = { + .atomic_print_state = mdp5_plane_atomic_print_state, + }; + ++static int mdp5_plane_prepare_fb(struct drm_plane *plane, ++ struct drm_plane_state *new_state) ++{ ++ struct msm_drm_private *priv = plane->dev->dev_private; ++ struct msm_kms *kms = priv->kms; ++ bool needs_dirtyfb = to_mdp5_plane_state(new_state)->needs_dirtyfb; ++ ++ if (!new_state->fb) ++ return 0; ++ ++ drm_gem_plane_helper_prepare_fb(plane, new_state); ++ ++ return msm_framebuffer_prepare(new_state->fb, kms->aspace, needs_dirtyfb); ++} ++ + static void mdp5_plane_cleanup_fb(struct drm_plane *plane, + struct drm_plane_state *old_state) + { + struct mdp5_kms *mdp5_kms = get_kms(plane); + struct msm_kms *kms = &mdp5_kms->base.base; + struct drm_framebuffer *fb = old_state->fb; ++ bool needed_dirtyfb = to_mdp5_plane_state(old_state)->needs_dirtyfb; + + if (!fb) + return; + + DBG("%s: cleanup: FB[%u]", plane->name, fb->base.id); +- msm_framebuffer_cleanup(fb, kms->aspace); ++ msm_framebuffer_cleanup(fb, kms->aspace, needed_dirtyfb); + } + + static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state, +@@ -452,7 +469,7 @@ static void mdp5_plane_atomic_async_update(struct drm_plane *plane, + } + + static const struct drm_plane_helper_funcs mdp5_plane_helper_funcs = { +- .prepare_fb = msm_atomic_prepare_fb, ++ .prepare_fb = mdp5_plane_prepare_fb, + .cleanup_fb = mdp5_plane_cleanup_fb, + .atomic_check = mdp5_plane_atomic_check, + .atomic_update = mdp5_plane_atomic_update, +diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c +index fab09e7c6efc3..458f4e4316dd4 100644 +--- a/drivers/gpu/drm/msm/msm_atomic.c ++++ b/drivers/gpu/drm/msm/msm_atomic.c +@@ -5,7 +5,6 @@ + */ + + #include <drm/drm_atomic_uapi.h> +-#include <drm/drm_gem_atomic_helper.h> + #include <drm/drm_vblank.h> + + #include "msm_atomic_trace.h" +@@ -13,20 +12,6 @@ + #include "msm_gem.h" + #include "msm_kms.h" + +-int msm_atomic_prepare_fb(struct drm_plane *plane, +- struct drm_plane_state *new_state) +-{ +- struct msm_drm_private *priv = plane->dev->dev_private; +- struct msm_kms *kms = priv->kms; +- +- if (!new_state->fb) +- return 0; +- +- drm_gem_plane_helper_prepare_fb(plane, new_state); +- +- return msm_framebuffer_prepare(new_state->fb, kms->aspace); +-} +- + /* + * Helpers to control vblanks while we flush.. basically just to ensure + * that vblank accounting is switched on, so we get valid seqn/timestamp +diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h +index bd5132bb9bde2..8488e49817e1e 100644 +--- a/drivers/gpu/drm/msm/msm_drv.h ++++ b/drivers/gpu/drm/msm/msm_drv.h +@@ -247,8 +247,6 @@ struct msm_format { + + struct msm_pending_timer; + +-int msm_atomic_prepare_fb(struct drm_plane *plane, +- struct drm_plane_state *new_state); + int msm_atomic_init_pending_timer(struct msm_pending_timer *timer, + struct msm_kms *kms, int crtc_idx); + void msm_atomic_destroy_pending_timer(struct msm_pending_timer *timer); +@@ -308,9 +306,9 @@ int msm_gem_prime_pin(struct drm_gem_object *obj); + void msm_gem_prime_unpin(struct drm_gem_object *obj); + + int msm_framebuffer_prepare(struct drm_framebuffer *fb, +- struct msm_gem_address_space *aspace); ++ struct msm_gem_address_space *aspace, bool needs_dirtyfb); + void msm_framebuffer_cleanup(struct drm_framebuffer *fb, +- struct msm_gem_address_space *aspace); ++ struct msm_gem_address_space *aspace, bool needed_dirtyfb); + uint32_t msm_framebuffer_iova(struct drm_framebuffer *fb, + struct msm_gem_address_space *aspace, int plane); + struct drm_gem_object *msm_framebuffer_bo(struct drm_framebuffer *fb, int plane); +diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c +index 4d34df5354e07..7137492fe78e2 100644 +--- a/drivers/gpu/drm/msm/msm_fb.c ++++ b/drivers/gpu/drm/msm/msm_fb.c +@@ -18,16 +18,36 @@ + struct msm_framebuffer { + struct drm_framebuffer base; + const struct msm_format *format; ++ ++ /* Count of # of attached planes which need dirtyfb: */ ++ refcount_t dirtyfb; + }; + #define to_msm_framebuffer(x) container_of(x, struct msm_framebuffer, base) + + static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, + const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos); + ++static int msm_framebuffer_dirtyfb(struct drm_framebuffer *fb, ++ struct drm_file *file_priv, unsigned int flags, ++ unsigned int color, struct drm_clip_rect *clips, ++ unsigned int num_clips) ++{ ++ struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); ++ ++ /* If this fb is not used on any display requiring pixel data to be ++ * flushed, then skip dirtyfb ++ */ ++ if (refcount_read(&msm_fb->dirtyfb) == 1) ++ return 0; ++ ++ return drm_atomic_helper_dirtyfb(fb, file_priv, flags, color, ++ clips, num_clips); ++} ++ + static const struct drm_framebuffer_funcs msm_framebuffer_funcs = { + .create_handle = drm_gem_fb_create_handle, + .destroy = drm_gem_fb_destroy, +- .dirty = drm_atomic_helper_dirtyfb, ++ .dirty = msm_framebuffer_dirtyfb, + }; + + #ifdef CONFIG_DEBUG_FS +@@ -48,17 +68,19 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m) + } + #endif + +-/* prepare/pin all the fb's bo's for scanout. Note that it is not valid +- * to prepare an fb more multiple different initiator 'id's. But that +- * should be fine, since only the scanout (mdpN) side of things needs +- * this, the gpu doesn't care about fb's. ++/* prepare/pin all the fb's bo's for scanout. + */ + int msm_framebuffer_prepare(struct drm_framebuffer *fb, +- struct msm_gem_address_space *aspace) ++ struct msm_gem_address_space *aspace, ++ bool needs_dirtyfb) + { ++ struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); + int ret, i, n = fb->format->num_planes; + uint64_t iova; + ++ if (needs_dirtyfb) ++ refcount_inc(&msm_fb->dirtyfb); ++ + for (i = 0; i < n; i++) { + ret = msm_gem_get_and_pin_iova(fb->obj[i], aspace, &iova); + drm_dbg_state(fb->dev, "FB[%u]: iova[%d]: %08llx (%d)", fb->base.id, i, iova, ret); +@@ -70,10 +92,15 @@ int msm_framebuffer_prepare(struct drm_framebuffer *fb, + } + + void msm_framebuffer_cleanup(struct drm_framebuffer *fb, +- struct msm_gem_address_space *aspace) ++ struct msm_gem_address_space *aspace, ++ bool needed_dirtyfb) + { ++ struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); + int i, n = fb->format->num_planes; + ++ if (needed_dirtyfb) ++ refcount_dec(&msm_fb->dirtyfb); ++ + for (i = 0; i < n; i++) + msm_gem_unpin_iova(fb->obj[i], aspace); + } +@@ -194,6 +221,8 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, + goto fail; + } + ++ refcount_set(&msm_fb->dirtyfb, 1); ++ + drm_dbg_state(dev, "create: FB ID: %d (%p)", fb->base.id, fb); + + return fb; +diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c +index 22b83a6577eb0..df83c4654e269 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_connector.c ++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c +@@ -1361,13 +1361,11 @@ nouveau_connector_create(struct drm_device *dev, + snprintf(aux_name, sizeof(aux_name), "sor-%04x-%04x", + dcbe->hasht, dcbe->hashm); + nv_connector->aux.name = kstrdup(aux_name, GFP_KERNEL); +- drm_dp_aux_init(&nv_connector->aux); +- if (ret) { +- NV_ERROR(drm, "Failed to init AUX adapter for sor-%04x-%04x: %d\n", +- dcbe->hasht, dcbe->hashm, ret); ++ if (!nv_connector->aux.name) { + kfree(nv_connector); +- return ERR_PTR(ret); ++ return ERR_PTR(-ENOMEM); + } ++ drm_dp_aux_init(&nv_connector->aux); + fallthrough; + default: + funcs = &nouveau_connector_funcs; +diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c +index 929de41c281f2..b8667bdc04ba0 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_display.c ++++ b/drivers/gpu/drm/nouveau/nouveau_display.c +@@ -518,7 +518,7 @@ nouveau_display_hpd_work(struct work_struct *work) + + pm_runtime_mark_last_busy(drm->dev->dev); + noop: +- pm_runtime_put_sync(drm->dev->dev); ++ pm_runtime_put_autosuspend(dev->dev); + } + + #ifdef CONFIG_ACPI +@@ -540,7 +540,7 @@ nouveau_display_acpi_ntfy(struct notifier_block *nb, unsigned long val, + * it's own hotplug events. + */ + pm_runtime_put_autosuspend(drm->dev->dev); +- } else if (ret == 0) { ++ } else if (ret == 0 || ret == -EINPROGRESS) { + /* We've started resuming the GPU already, so + * it will handle scheduling a full reprobe + * itself +diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c +index 4f9b3aa5deda9..20ac1ce2c0f14 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c ++++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c +@@ -466,7 +466,7 @@ nouveau_fbcon_set_suspend_work(struct work_struct *work) + if (state == FBINFO_STATE_RUNNING) { + nouveau_fbcon_hotplug_resume(drm->fbcon); + pm_runtime_mark_last_busy(drm->dev->dev); +- pm_runtime_put_sync(drm->dev->dev); ++ pm_runtime_put_autosuspend(drm->dev->dev); + } + } + +diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c +index 64e423dddd9e7..6c318e41bde04 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c +@@ -33,7 +33,7 @@ nvbios_addr(struct nvkm_bios *bios, u32 *addr, u8 size) + { + u32 p = *addr; + +- if (*addr > bios->image0_size && bios->imaged_addr) { ++ if (*addr >= bios->image0_size && bios->imaged_addr) { + *addr -= bios->image0_size; + *addr += bios->imaged_addr; + } +diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig +index af1402d83d51c..479ffdb64486e 100644 +--- a/drivers/gpu/drm/panel/Kconfig ++++ b/drivers/gpu/drm/panel/Kconfig +@@ -373,6 +373,8 @@ config DRM_PANEL_SAMSUNG_ATNA33XC20 + depends on OF + depends on BACKLIGHT_CLASS_DEVICE + depends on PM ++ select DRM_DISPLAY_DP_HELPER ++ select DRM_DISPLAY_HELPER + select DRM_DP_AUX_BUS + help + DRM panel driver for the Samsung ATNA33XC20 panel. This panel can't +diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c +index de533f3727648..e48e357ea4f18 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_drv.c ++++ b/drivers/gpu/drm/panfrost/panfrost_drv.c +@@ -418,7 +418,7 @@ static int panfrost_ioctl_madvise(struct drm_device *dev, void *data, + } + } + +- args->retained = drm_gem_shmem_madvise(gem_obj, args->madv); ++ args->retained = drm_gem_shmem_madvise(&bo->base, args->madv); + + if (args->retained) { + if (args->madv == PANFROST_MADV_DONTNEED) +diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c +index 23377481f4e31..6d9bdb9180cb7 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_gem.c ++++ b/drivers/gpu/drm/panfrost/panfrost_gem.c +@@ -49,7 +49,7 @@ static void panfrost_gem_free_object(struct drm_gem_object *obj) + kvfree(bo->sgts); + } + +- drm_gem_shmem_free_object(obj); ++ drm_gem_shmem_free(&bo->base); + } + + struct panfrost_gem_mapping * +@@ -187,23 +187,25 @@ void panfrost_gem_close(struct drm_gem_object *obj, struct drm_file *file_priv) + + static int panfrost_gem_pin(struct drm_gem_object *obj) + { +- if (to_panfrost_bo(obj)->is_heap) ++ struct panfrost_gem_object *bo = to_panfrost_bo(obj); ++ ++ if (bo->is_heap) + return -EINVAL; + +- return drm_gem_shmem_pin(obj); ++ return drm_gem_shmem_pin(&bo->base); + } + + static const struct drm_gem_object_funcs panfrost_gem_funcs = { + .free = panfrost_gem_free_object, + .open = panfrost_gem_open, + .close = panfrost_gem_close, +- .print_info = drm_gem_shmem_print_info, ++ .print_info = drm_gem_shmem_object_print_info, + .pin = panfrost_gem_pin, +- .unpin = drm_gem_shmem_unpin, +- .get_sg_table = drm_gem_shmem_get_sg_table, +- .vmap = drm_gem_shmem_vmap, +- .vunmap = drm_gem_shmem_vunmap, +- .mmap = drm_gem_shmem_mmap, ++ .unpin = drm_gem_shmem_object_unpin, ++ .get_sg_table = drm_gem_shmem_object_get_sg_table, ++ .vmap = drm_gem_shmem_object_vmap, ++ .vunmap = drm_gem_shmem_object_vunmap, ++ .mmap = drm_gem_shmem_object_mmap, + }; + + /** +diff --git a/drivers/gpu/drm/panfrost/panfrost_gem_shrinker.c b/drivers/gpu/drm/panfrost/panfrost_gem_shrinker.c +index 1b9f68d8e9aa6..b0142341e2235 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_gem_shrinker.c ++++ b/drivers/gpu/drm/panfrost/panfrost_gem_shrinker.c +@@ -52,7 +52,7 @@ static bool panfrost_gem_purge(struct drm_gem_object *obj) + goto unlock_mappings; + + panfrost_gem_teardown_mappings_locked(bo); +- drm_gem_shmem_purge_locked(obj); ++ drm_gem_shmem_purge_locked(&bo->base); + ret = true; + + mutex_unlock(&shmem->pages_lock); +diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c +index c0189cc9a2f17..c3292a6bd1ae8 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c ++++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c +@@ -288,7 +288,8 @@ static int mmu_map_sg(struct panfrost_device *pfdev, struct panfrost_mmu *mmu, + int panfrost_mmu_map(struct panfrost_gem_mapping *mapping) + { + struct panfrost_gem_object *bo = mapping->obj; +- struct drm_gem_object *obj = &bo->base.base; ++ struct drm_gem_shmem_object *shmem = &bo->base; ++ struct drm_gem_object *obj = &shmem->base; + struct panfrost_device *pfdev = to_panfrost_device(obj->dev); + struct sg_table *sgt; + int prot = IOMMU_READ | IOMMU_WRITE; +@@ -299,7 +300,7 @@ int panfrost_mmu_map(struct panfrost_gem_mapping *mapping) + if (bo->noexec) + prot |= IOMMU_NOEXEC; + +- sgt = drm_gem_shmem_get_pages_sgt(obj); ++ sgt = drm_gem_shmem_get_pages_sgt(shmem); + if (WARN_ON(IS_ERR(sgt))) + return PTR_ERR(sgt); + +diff --git a/drivers/gpu/drm/panfrost/panfrost_perfcnt.c b/drivers/gpu/drm/panfrost/panfrost_perfcnt.c +index 5ab03d605f57b..9d9c067c1d705 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_perfcnt.c ++++ b/drivers/gpu/drm/panfrost/panfrost_perfcnt.c +@@ -105,7 +105,7 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev, + goto err_close_bo; + } + +- ret = drm_gem_shmem_vmap(&bo->base, &map); ++ ret = drm_gem_shmem_vmap(bo, &map); + if (ret) + goto err_put_mapping; + perfcnt->buf = map.vaddr; +@@ -164,7 +164,7 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev, + return 0; + + err_vunmap: +- drm_gem_shmem_vunmap(&bo->base, &map); ++ drm_gem_shmem_vunmap(bo, &map); + err_put_mapping: + panfrost_gem_mapping_put(perfcnt->mapping); + err_close_bo: +@@ -194,7 +194,7 @@ static int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev, + GPU_PERFCNT_CFG_MODE(GPU_PERFCNT_CFG_MODE_OFF)); + + perfcnt->user = NULL; +- drm_gem_shmem_vunmap(&perfcnt->mapping->obj->base.base, &map); ++ drm_gem_shmem_vunmap(&perfcnt->mapping->obj->base, &map); + perfcnt->buf = NULL; + panfrost_gem_close(&perfcnt->mapping->obj->base.base, file_priv); + panfrost_mmu_as_put(pfdev, perfcnt->mapping->mmu); +diff --git a/drivers/gpu/drm/radeon/.gitignore b/drivers/gpu/drm/radeon/.gitignore +index 9c1a941539836..d8777383a64aa 100644 +--- a/drivers/gpu/drm/radeon/.gitignore ++++ b/drivers/gpu/drm/radeon/.gitignore +@@ -1,4 +1,4 @@ +-# SPDX-License-Identifier: GPL-2.0-only ++# SPDX-License-Identifier: MIT + mkregtable + *_reg_safe.h + +diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig +index 6f60f4840cc58..52819e7f1fca1 100644 +--- a/drivers/gpu/drm/radeon/Kconfig ++++ b/drivers/gpu/drm/radeon/Kconfig +@@ -1,4 +1,4 @@ +-# SPDX-License-Identifier: GPL-2.0-only ++# SPDX-License-Identifier: MIT + config DRM_RADEON_USERPTR + bool "Always enable userptr support" + depends on DRM_RADEON +diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile +index 11c97edde54dd..3d502f1bbfcbe 100644 +--- a/drivers/gpu/drm/radeon/Makefile ++++ b/drivers/gpu/drm/radeon/Makefile +@@ -1,4 +1,4 @@ +-# SPDX-License-Identifier: GPL-2.0 ++# SPDX-License-Identifier: MIT + # + # Makefile for the drm device driver. This driver provides support for the + # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. +diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c +index 769f666335ac4..672d2239293e0 100644 +--- a/drivers/gpu/drm/radeon/ni_dpm.c ++++ b/drivers/gpu/drm/radeon/ni_dpm.c +@@ -2741,10 +2741,10 @@ static int ni_set_mc_special_registers(struct radeon_device *rdev, + table->mc_reg_table_entry[k].mc_data[j] |= 0x100; + } + j++; +- if (j > SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE) +- return -EINVAL; + break; + case MC_SEQ_RESERVE_M >> 2: ++ if (j >= SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE) ++ return -EINVAL; + temp_reg = RREG32(MC_PMG_CMD_MRS1); + table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS1 >> 2; + table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS1_LP >> 2; +@@ -2753,8 +2753,6 @@ static int ni_set_mc_special_registers(struct radeon_device *rdev, + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + j++; +- if (j > SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE) +- return -EINVAL; + break; + default: + break; +diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +index ade2327a10e2c..512581698a1e0 100644 +--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c ++++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +@@ -398,7 +398,15 @@ static int rockchip_dp_probe(struct platform_device *pdev) + if (IS_ERR(dp->adp)) + return PTR_ERR(dp->adp); + +- return component_add(dev, &rockchip_dp_component_ops); ++ ret = component_add(dev, &rockchip_dp_component_ops); ++ if (ret) ++ goto err_dp_remove; ++ ++ return 0; ++ ++err_dp_remove: ++ analogix_dp_remove(dp->adp); ++ return ret; + } + + static int rockchip_dp_remove(struct platform_device *pdev) +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 8b4287d403790..d5b74ea06a451 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -1550,6 +1550,9 @@ static struct drm_crtc_state *vop_crtc_duplicate_state(struct drm_crtc *crtc) + { + struct rockchip_crtc_state *rockchip_state; + ++ if (WARN_ON(!crtc->state)) ++ return NULL; ++ + rockchip_state = kzalloc(sizeof(*rockchip_state), GFP_KERNEL); + if (!rockchip_state) + return NULL; +diff --git a/drivers/gpu/drm/tiny/st7735r.c b/drivers/gpu/drm/tiny/st7735r.c +index fc40dd10efa8f..713e4b2862105 100644 +--- a/drivers/gpu/drm/tiny/st7735r.c ++++ b/drivers/gpu/drm/tiny/st7735r.c +@@ -174,6 +174,7 @@ MODULE_DEVICE_TABLE(of, st7735r_of_match); + + static const struct spi_device_id st7735r_id[] = { + { "jd-t18003-t01", (uintptr_t)&jd_t18003_t01_cfg }, ++ { "rh128128t", (uintptr_t)&rh128128t_cfg }, + { }, + }; + MODULE_DEVICE_TABLE(spi, st7735r_id); +diff --git a/drivers/gpu/drm/v3d/v3d_bo.c b/drivers/gpu/drm/v3d/v3d_bo.c +index 6a8731ab9d7d0..0d9af62f69ad1 100644 +--- a/drivers/gpu/drm/v3d/v3d_bo.c ++++ b/drivers/gpu/drm/v3d/v3d_bo.c +@@ -47,18 +47,18 @@ void v3d_free_object(struct drm_gem_object *obj) + /* GPU execution may have dirtied any pages in the BO. */ + bo->base.pages_mark_dirty_on_put = true; + +- drm_gem_shmem_free_object(obj); ++ drm_gem_shmem_free(&bo->base); + } + + static const struct drm_gem_object_funcs v3d_gem_funcs = { + .free = v3d_free_object, +- .print_info = drm_gem_shmem_print_info, +- .pin = drm_gem_shmem_pin, +- .unpin = drm_gem_shmem_unpin, +- .get_sg_table = drm_gem_shmem_get_sg_table, +- .vmap = drm_gem_shmem_vmap, +- .vunmap = drm_gem_shmem_vunmap, +- .mmap = drm_gem_shmem_mmap, ++ .print_info = drm_gem_shmem_object_print_info, ++ .pin = drm_gem_shmem_object_pin, ++ .unpin = drm_gem_shmem_object_unpin, ++ .get_sg_table = drm_gem_shmem_object_get_sg_table, ++ .vmap = drm_gem_shmem_object_vmap, ++ .vunmap = drm_gem_shmem_object_vunmap, ++ .mmap = drm_gem_shmem_object_mmap, + }; + + /* gem_create_object function for allocating a BO struct and doing +@@ -95,7 +95,7 @@ v3d_bo_create_finish(struct drm_gem_object *obj) + /* So far we pin the BO in the MMU for its lifetime, so use + * shmem's helper for getting a lifetime sgt. + */ +- sgt = drm_gem_shmem_get_pages_sgt(&bo->base.base); ++ sgt = drm_gem_shmem_get_pages_sgt(&bo->base); + if (IS_ERR(sgt)) + return PTR_ERR(sgt); + +@@ -141,7 +141,7 @@ struct v3d_bo *v3d_bo_create(struct drm_device *dev, struct drm_file *file_priv, + return bo; + + free_obj: +- drm_gem_shmem_free_object(&shmem_obj->base); ++ drm_gem_shmem_free(shmem_obj); + return ERR_PTR(ret); + } + +@@ -159,7 +159,7 @@ v3d_prime_import_sg_table(struct drm_device *dev, + + ret = v3d_bo_create_finish(obj); + if (ret) { +- drm_gem_shmem_free_object(obj); ++ drm_gem_shmem_free(&to_v3d_bo(obj)->base); + return ERR_PTR(ret); + } + +diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c +index 88dbb282d15c4..3b8576f193214 100644 +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -330,7 +330,8 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_atomic_state *s + u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; + bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 || + vc4_encoder->type == VC4_ENCODER_TYPE_DSI1); +- u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24; ++ bool is_dsi1 = vc4_encoder->type == VC4_ENCODER_TYPE_DSI1; ++ u32 format = is_dsi1 ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24; + u8 ppc = pv_data->pixels_per_clock; + bool debug_dump_regs = false; + +@@ -356,7 +357,8 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_atomic_state *s + PV_HORZB_HACTIVE)); + + CRTC_WRITE(PV_VERTA, +- VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, ++ VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end + ++ interlace, + PV_VERTA_VBP) | + VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, + PV_VERTA_VSYNC)); +@@ -368,7 +370,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_atomic_state *s + if (interlace) { + CRTC_WRITE(PV_VERTA_EVEN, + VC4_SET_FIELD(mode->crtc_vtotal - +- mode->crtc_vsync_end - 1, ++ mode->crtc_vsync_end, + PV_VERTA_VBP) | + VC4_SET_FIELD(mode->crtc_vsync_end - + mode->crtc_vsync_start, +@@ -388,7 +390,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_atomic_state *s + PV_VCONTROL_CONTINUOUS | + (is_dsi ? PV_VCONTROL_DSI : 0) | + PV_VCONTROL_INTERLACE | +- VC4_SET_FIELD(mode->htotal * pixel_rep / 2, ++ VC4_SET_FIELD(mode->htotal * pixel_rep / (2 * ppc), + PV_VCONTROL_ODD_DELAY)); + CRTC_WRITE(PV_VSYNCD_EVEN, 0); + } else { +diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c +index f6c16c5aee683..ef8fa2850ed6a 100644 +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -214,6 +214,15 @@ static void vc4_match_add_drivers(struct device *dev, + } + } + ++static const struct of_device_id vc4_dma_range_matches[] = { ++ { .compatible = "brcm,bcm2711-hvs" }, ++ { .compatible = "brcm,bcm2835-hvs" }, ++ { .compatible = "brcm,bcm2835-v3d" }, ++ { .compatible = "brcm,cygnus-v3d" }, ++ { .compatible = "brcm,vc4-v3d" }, ++ {} ++}; ++ + static int vc4_drm_bind(struct device *dev) + { + struct platform_device *pdev = to_platform_device(dev); +@@ -231,6 +240,16 @@ static int vc4_drm_bind(struct device *dev) + vc4_drm_driver.driver_features &= ~DRIVER_RENDER; + of_node_put(node); + ++ node = of_find_matching_node_and_match(NULL, vc4_dma_range_matches, ++ NULL); ++ if (node) { ++ ret = of_dma_configure(dev, node, true); ++ of_node_put(node); ++ ++ if (ret) ++ return ret; ++ } ++ + vc4 = devm_drm_dev_alloc(dev, &vc4_drm_driver, struct vc4_dev, base); + if (IS_ERR(vc4)) + return PTR_ERR(vc4); +diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c +index ca85063166609..b7b2c76770dc6 100644 +--- a/drivers/gpu/drm/vc4/vc4_dsi.c ++++ b/drivers/gpu/drm/vc4/vc4_dsi.c +@@ -181,8 +181,50 @@ + + #define DSI0_TXPKT_PIX_FIFO 0x20 /* AKA PIX_FIFO */ + +-#define DSI0_INT_STAT 0x24 +-#define DSI0_INT_EN 0x28 ++#define DSI0_INT_STAT 0x24 ++#define DSI0_INT_EN 0x28 ++# define DSI0_INT_FIFO_ERR BIT(25) ++# define DSI0_INT_CMDC_DONE_MASK VC4_MASK(24, 23) ++# define DSI0_INT_CMDC_DONE_SHIFT 23 ++# define DSI0_INT_CMDC_DONE_NO_REPEAT 1 ++# define DSI0_INT_CMDC_DONE_REPEAT 3 ++# define DSI0_INT_PHY_DIR_RTF BIT(22) ++# define DSI0_INT_PHY_D1_ULPS BIT(21) ++# define DSI0_INT_PHY_D1_STOP BIT(20) ++# define DSI0_INT_PHY_RXLPDT BIT(19) ++# define DSI0_INT_PHY_RXTRIG BIT(18) ++# define DSI0_INT_PHY_D0_ULPS BIT(17) ++# define DSI0_INT_PHY_D0_LPDT BIT(16) ++# define DSI0_INT_PHY_D0_FTR BIT(15) ++# define DSI0_INT_PHY_D0_STOP BIT(14) ++/* Signaled when the clock lane enters the given state. */ ++# define DSI0_INT_PHY_CLK_ULPS BIT(13) ++# define DSI0_INT_PHY_CLK_HS BIT(12) ++# define DSI0_INT_PHY_CLK_FTR BIT(11) ++/* Signaled on timeouts */ ++# define DSI0_INT_PR_TO BIT(10) ++# define DSI0_INT_TA_TO BIT(9) ++# define DSI0_INT_LPRX_TO BIT(8) ++# define DSI0_INT_HSTX_TO BIT(7) ++/* Contention on a line when trying to drive the line low */ ++# define DSI0_INT_ERR_CONT_LP1 BIT(6) ++# define DSI0_INT_ERR_CONT_LP0 BIT(5) ++/* Control error: incorrect line state sequence on data lane 0. */ ++# define DSI0_INT_ERR_CONTROL BIT(4) ++# define DSI0_INT_ERR_SYNC_ESC BIT(3) ++# define DSI0_INT_RX2_PKT BIT(2) ++# define DSI0_INT_RX1_PKT BIT(1) ++# define DSI0_INT_CMD_PKT BIT(0) ++ ++#define DSI0_INTERRUPTS_ALWAYS_ENABLED (DSI0_INT_ERR_SYNC_ESC | \ ++ DSI0_INT_ERR_CONTROL | \ ++ DSI0_INT_ERR_CONT_LP0 | \ ++ DSI0_INT_ERR_CONT_LP1 | \ ++ DSI0_INT_HSTX_TO | \ ++ DSI0_INT_LPRX_TO | \ ++ DSI0_INT_TA_TO | \ ++ DSI0_INT_PR_TO) ++ + # define DSI1_INT_PHY_D3_ULPS BIT(30) + # define DSI1_INT_PHY_D3_STOP BIT(29) + # define DSI1_INT_PHY_D2_ULPS BIT(28) +@@ -761,6 +803,9 @@ static void vc4_dsi_encoder_disable(struct drm_encoder *encoder) + list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) { + if (iter->funcs->disable) + iter->funcs->disable(iter); ++ ++ if (iter == dsi->bridge) ++ break; + } + + vc4_dsi_ulps(dsi, true); +@@ -805,11 +850,9 @@ static bool vc4_dsi_encoder_mode_fixup(struct drm_encoder *encoder, + /* Find what divider gets us a faster clock than the requested + * pixel clock. + */ +- for (divider = 1; divider < 8; divider++) { +- if (parent_rate / divider < pll_clock) { +- divider--; ++ for (divider = 1; divider < 255; divider++) { ++ if (parent_rate / (divider + 1) < pll_clock) + break; +- } + } + + /* Now that we've picked a PLL divider, calculate back to its +@@ -894,6 +937,9 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) + + DSI_PORT_WRITE(PHY_AFEC0, afec0); + ++ /* AFEC reset hold time */ ++ mdelay(1); ++ + DSI_PORT_WRITE(PHY_AFEC1, + VC4_SET_FIELD(6, DSI0_PHY_AFEC1_IDR_DLANE1) | + VC4_SET_FIELD(6, DSI0_PHY_AFEC1_IDR_DLANE0) | +@@ -1060,12 +1106,9 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) + DSI_PORT_WRITE(CTRL, DSI_PORT_READ(CTRL) | DSI1_CTRL_EN); + + /* Bring AFE out of reset. */ +- if (dsi->variant->port == 0) { +- } else { +- DSI_PORT_WRITE(PHY_AFEC0, +- DSI_PORT_READ(PHY_AFEC0) & +- ~DSI1_PHY_AFEC0_RESET); +- } ++ DSI_PORT_WRITE(PHY_AFEC0, ++ DSI_PORT_READ(PHY_AFEC0) & ++ ~DSI_PORT_BIT(PHY_AFEC0_RESET)); + + vc4_dsi_ulps(dsi, false); + +@@ -1184,13 +1227,28 @@ static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host, + /* Enable the appropriate interrupt for the transfer completion. */ + dsi->xfer_result = 0; + reinit_completion(&dsi->xfer_completion); +- DSI_PORT_WRITE(INT_STAT, DSI1_INT_TXPKT1_DONE | DSI1_INT_PHY_DIR_RTF); +- if (msg->rx_len) { +- DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED | +- DSI1_INT_PHY_DIR_RTF)); ++ if (dsi->variant->port == 0) { ++ DSI_PORT_WRITE(INT_STAT, ++ DSI0_INT_CMDC_DONE_MASK | DSI1_INT_PHY_DIR_RTF); ++ if (msg->rx_len) { ++ DSI_PORT_WRITE(INT_EN, (DSI0_INTERRUPTS_ALWAYS_ENABLED | ++ DSI0_INT_PHY_DIR_RTF)); ++ } else { ++ DSI_PORT_WRITE(INT_EN, ++ (DSI0_INTERRUPTS_ALWAYS_ENABLED | ++ VC4_SET_FIELD(DSI0_INT_CMDC_DONE_NO_REPEAT, ++ DSI0_INT_CMDC_DONE))); ++ } + } else { +- DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED | +- DSI1_INT_TXPKT1_DONE)); ++ DSI_PORT_WRITE(INT_STAT, ++ DSI1_INT_TXPKT1_DONE | DSI1_INT_PHY_DIR_RTF); ++ if (msg->rx_len) { ++ DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED | ++ DSI1_INT_PHY_DIR_RTF)); ++ } else { ++ DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED | ++ DSI1_INT_TXPKT1_DONE)); ++ } + } + + /* Send the packet. */ +@@ -1207,7 +1265,7 @@ static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host, + ret = dsi->xfer_result; + } + +- DSI_PORT_WRITE(INT_EN, DSI1_INTERRUPTS_ALWAYS_ENABLED); ++ DSI_PORT_WRITE(INT_EN, DSI_PORT_BIT(INTERRUPTS_ALWAYS_ENABLED)); + + if (ret) + goto reset_fifo_and_return; +@@ -1253,7 +1311,7 @@ reset_fifo_and_return: + DSI_PORT_BIT(CTRL_RESET_FIFOS)); + + DSI_PORT_WRITE(TXPKT1C, 0); +- DSI_PORT_WRITE(INT_EN, DSI1_INTERRUPTS_ALWAYS_ENABLED); ++ DSI_PORT_WRITE(INT_EN, DSI_PORT_BIT(INTERRUPTS_ALWAYS_ENABLED)); + return ret; + } + +@@ -1390,26 +1448,28 @@ static irqreturn_t vc4_dsi_irq_handler(int irq, void *data) + DSI_PORT_WRITE(INT_STAT, stat); + + dsi_handle_error(dsi, &ret, stat, +- DSI1_INT_ERR_SYNC_ESC, "LPDT sync"); ++ DSI_PORT_BIT(INT_ERR_SYNC_ESC), "LPDT sync"); + dsi_handle_error(dsi, &ret, stat, +- DSI1_INT_ERR_CONTROL, "data lane 0 sequence"); ++ DSI_PORT_BIT(INT_ERR_CONTROL), "data lane 0 sequence"); + dsi_handle_error(dsi, &ret, stat, +- DSI1_INT_ERR_CONT_LP0, "LP0 contention"); ++ DSI_PORT_BIT(INT_ERR_CONT_LP0), "LP0 contention"); + dsi_handle_error(dsi, &ret, stat, +- DSI1_INT_ERR_CONT_LP1, "LP1 contention"); ++ DSI_PORT_BIT(INT_ERR_CONT_LP1), "LP1 contention"); + dsi_handle_error(dsi, &ret, stat, +- DSI1_INT_HSTX_TO, "HSTX timeout"); ++ DSI_PORT_BIT(INT_HSTX_TO), "HSTX timeout"); + dsi_handle_error(dsi, &ret, stat, +- DSI1_INT_LPRX_TO, "LPRX timeout"); ++ DSI_PORT_BIT(INT_LPRX_TO), "LPRX timeout"); + dsi_handle_error(dsi, &ret, stat, +- DSI1_INT_TA_TO, "turnaround timeout"); ++ DSI_PORT_BIT(INT_TA_TO), "turnaround timeout"); + dsi_handle_error(dsi, &ret, stat, +- DSI1_INT_PR_TO, "peripheral reset timeout"); ++ DSI_PORT_BIT(INT_PR_TO), "peripheral reset timeout"); + +- if (stat & (DSI1_INT_TXPKT1_DONE | DSI1_INT_PHY_DIR_RTF)) { ++ if (stat & ((dsi->variant->port ? DSI1_INT_TXPKT1_DONE : ++ DSI0_INT_CMDC_DONE_MASK) | ++ DSI_PORT_BIT(INT_PHY_DIR_RTF))) { + complete(&dsi->xfer_completion); + ret = IRQ_HANDLED; +- } else if (stat & DSI1_INT_HSTX_TO) { ++ } else if (stat & DSI_PORT_BIT(INT_HSTX_TO)) { + complete(&dsi->xfer_completion); + dsi->xfer_result = -ETIMEDOUT; + ret = IRQ_HANDLED; +@@ -1487,22 +1547,32 @@ vc4_dsi_init_phy_clocks(struct vc4_dsi *dsi) + dsi->clk_onecell); + } + ++static void vc4_dsi_dma_mem_release(void *ptr) ++{ ++ struct vc4_dsi *dsi = ptr; ++ struct device *dev = &dsi->pdev->dev; ++ ++ dma_free_coherent(dev, 4, dsi->reg_dma_mem, dsi->reg_dma_paddr); ++ dsi->reg_dma_mem = NULL; ++} ++ ++static void vc4_dsi_dma_chan_release(void *ptr) ++{ ++ struct vc4_dsi *dsi = ptr; ++ ++ dma_release_channel(dsi->reg_dma_chan); ++ dsi->reg_dma_chan = NULL; ++} ++ + static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) + { + struct platform_device *pdev = to_platform_device(dev); + struct drm_device *drm = dev_get_drvdata(master); + struct vc4_dsi *dsi = dev_get_drvdata(dev); + struct vc4_dsi_encoder *vc4_dsi_encoder; +- struct drm_panel *panel; +- const struct of_device_id *match; +- dma_cap_mask_t dma_mask; + int ret; + +- match = of_match_device(vc4_dsi_dt_match, dev); +- if (!match) +- return -ENODEV; +- +- dsi->variant = match->data; ++ dsi->variant = of_device_get_match_data(dev); + + vc4_dsi_encoder = devm_kzalloc(dev, sizeof(*vc4_dsi_encoder), + GFP_KERNEL); +@@ -1510,7 +1580,8 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) + return -ENOMEM; + + INIT_LIST_HEAD(&dsi->bridge_chain); +- vc4_dsi_encoder->base.type = VC4_ENCODER_TYPE_DSI1; ++ vc4_dsi_encoder->base.type = dsi->variant->port ? ++ VC4_ENCODER_TYPE_DSI1 : VC4_ENCODER_TYPE_DSI0; + vc4_dsi_encoder->dsi = dsi; + dsi->encoder = &vc4_dsi_encoder->base.base; + +@@ -1533,6 +1604,8 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) + * so set up a channel for talking to it. + */ + if (dsi->variant->broken_axi_workaround) { ++ dma_cap_mask_t dma_mask; ++ + dsi->reg_dma_mem = dma_alloc_coherent(dev, 4, + &dsi->reg_dma_paddr, + GFP_KERNEL); +@@ -1541,8 +1614,13 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) + return -ENOMEM; + } + ++ ret = devm_add_action_or_reset(dev, vc4_dsi_dma_mem_release, dsi); ++ if (ret) ++ return ret; ++ + dma_cap_zero(dma_mask); + dma_cap_set(DMA_MEMCPY, dma_mask); ++ + dsi->reg_dma_chan = dma_request_chan_by_mask(&dma_mask); + if (IS_ERR(dsi->reg_dma_chan)) { + ret = PTR_ERR(dsi->reg_dma_chan); +@@ -1552,6 +1630,10 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) + return ret; + } + ++ ret = devm_add_action_or_reset(dev, vc4_dsi_dma_chan_release, dsi); ++ if (ret) ++ return ret; ++ + /* Get the physical address of the device's registers. The + * struct resource for the regs gives us the bus address + * instead. +@@ -1605,27 +1687,9 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) + return ret; + } + +- ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, +- &panel, &dsi->bridge); +- if (ret) { +- /* If the bridge or panel pointed by dev->of_node is not +- * enabled, just return 0 here so that we don't prevent the DRM +- * dev from being registered. Of course that means the DSI +- * encoder won't be exposed, but that's not a problem since +- * nothing is connected to it. +- */ +- if (ret == -ENODEV) +- return 0; +- +- return ret; +- } +- +- if (panel) { +- dsi->bridge = devm_drm_panel_bridge_add_typed(dev, panel, +- DRM_MODE_CONNECTOR_DSI); +- if (IS_ERR(dsi->bridge)) +- return PTR_ERR(dsi->bridge); +- } ++ dsi->bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0); ++ if (IS_ERR(dsi->bridge)) ++ return PTR_ERR(dsi->bridge); + + /* The esc clock rate is supposed to always be 100Mhz. */ + ret = clk_set_rate(dsi->escape_clock, 100 * 1000000); +@@ -1663,8 +1727,7 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master, + { + struct vc4_dsi *dsi = dev_get_drvdata(dev); + +- if (dsi->bridge) +- pm_runtime_disable(dev); ++ pm_runtime_disable(dev); + + /* + * Restore the bridge_chain so the bridge detach procedure can happen +diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c +index ef7bea7c43a0f..10cf623d28303 100644 +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -79,6 +79,9 @@ + #define VC5_HDMI_VERTB_VSPO_SHIFT 16 + #define VC5_HDMI_VERTB_VSPO_MASK VC4_MASK(29, 16) + ++#define VC5_HDMI_MISC_CONTROL_PIXEL_REP_SHIFT 0 ++#define VC5_HDMI_MISC_CONTROL_PIXEL_REP_MASK VC4_MASK(3, 0) ++ + #define VC5_HDMI_SCRAMBLER_CTL_ENABLE BIT(0) + + #define VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_SHIFT 8 +@@ -173,9 +176,9 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) + + WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); + +- if (vc4_hdmi->hpd_gpio && +- gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio)) { +- connected = true; ++ if (vc4_hdmi->hpd_gpio) { ++ if (gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio)) ++ connected = true; + } else if (drm_probe_ddc(vc4_hdmi->ddc)) { + connected = true; + } else if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED) { +@@ -735,12 +738,12 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, + VC4_HDMI_VERTA_VFP) | + VC4_SET_FIELD(mode->crtc_vdisplay, VC4_HDMI_VERTA_VAL)); + u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) | +- VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, ++ VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end + ++ interlaced, + VC4_HDMI_VERTB_VBP)); + u32 vertb_even = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) | + VC4_SET_FIELD(mode->crtc_vtotal - +- mode->crtc_vsync_end - +- interlaced, ++ mode->crtc_vsync_end, + VC4_HDMI_VERTB_VBP)); + + HDMI_WRITE(HDMI_HORZA, +@@ -780,13 +783,13 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, + VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, + VC5_HDMI_VERTA_VFP) | + VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL)); +- u32 vertb = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) | ++ u32 vertb = (VC4_SET_FIELD(mode->htotal >> (2 - pixel_rep), ++ VC5_HDMI_VERTB_VSPO) | + VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, + VC4_HDMI_VERTB_VBP)); + u32 vertb_even = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) | + VC4_SET_FIELD(mode->crtc_vtotal - +- mode->crtc_vsync_end - +- interlaced, ++ mode->crtc_vsync_end - interlaced, + VC4_HDMI_VERTB_VBP)); + unsigned char gcp; + bool gcp_en; +@@ -849,6 +852,11 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, + reg |= gcp_en ? VC5_HDMI_GCP_CONFIG_GCP_ENABLE : 0; + HDMI_WRITE(HDMI_GCP_CONFIG, reg); + ++ reg = HDMI_READ(HDMI_MISC_CONTROL); ++ reg &= ~VC5_HDMI_MISC_CONTROL_PIXEL_REP_MASK; ++ reg |= VC4_SET_FIELD(0, VC5_HDMI_MISC_CONTROL_PIXEL_REP); ++ HDMI_WRITE(HDMI_MISC_CONTROL, reg); ++ + HDMI_WRITE(HDMI_CLOCK_STOP, 0); + } + +@@ -1383,10 +1391,10 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data, + + /* Set the MAI threshold */ + HDMI_WRITE(HDMI_MAI_THR, +- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) | +- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) | +- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) | +- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW)); ++ VC4_SET_FIELD(0x08, VC4_HD_MAI_THR_PANICHIGH) | ++ VC4_SET_FIELD(0x08, VC4_HD_MAI_THR_PANICLOW) | ++ VC4_SET_FIELD(0x06, VC4_HD_MAI_THR_DREQHIGH) | ++ VC4_SET_FIELD(0x08, VC4_HD_MAI_THR_DREQLOW)); + + HDMI_WRITE(HDMI_MAI_CONFIG, + VC4_HDMI_MAI_CONFIG_BIT_REVERSE | +@@ -1470,12 +1478,12 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) + struct device *dev = &vc4_hdmi->pdev->dev; + struct platform_device *codec_pdev; + const __be32 *addr; +- int index; ++ int index, len; + int ret; + +- if (!of_find_property(dev->of_node, "dmas", NULL)) { ++ if (!of_find_property(dev->of_node, "dmas", &len) || !len) { + dev_warn(dev, +- "'dmas' DT property is missing, no HDMI audio\n"); ++ "'dmas' DT property is missing or empty, no HDMI audio\n"); + return 0; + } + +diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h +index 19d2fdc446bca..f126fa425a1d8 100644 +--- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h +@@ -123,6 +123,7 @@ enum vc4_hdmi_field { + HDMI_VERTB0, + HDMI_VERTB1, + HDMI_VID_CTL, ++ HDMI_MISC_CONTROL, + }; + + struct vc4_hdmi_register { +@@ -233,6 +234,7 @@ static const struct vc4_hdmi_register __maybe_unused vc5_hdmi_hdmi0_fields[] = { + VC4_HDMI_REG(HDMI_VERTB0, 0x0f0), + VC4_HDMI_REG(HDMI_VERTA1, 0x0f4), + VC4_HDMI_REG(HDMI_VERTB1, 0x0f8), ++ VC4_HDMI_REG(HDMI_MISC_CONTROL, 0x100), + VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c), + VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0), + VC4_HDMI_REG(HDMI_DEEP_COLOR_CONFIG_1, 0x170), +@@ -313,6 +315,7 @@ static const struct vc4_hdmi_register __maybe_unused vc5_hdmi_hdmi1_fields[] = { + VC4_HDMI_REG(HDMI_VERTB0, 0x0f0), + VC4_HDMI_REG(HDMI_VERTA1, 0x0f4), + VC4_HDMI_REG(HDMI_VERTB1, 0x0f8), ++ VC4_HDMI_REG(HDMI_MISC_CONTROL, 0x100), + VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c), + VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0), + VC4_HDMI_REG(HDMI_DEEP_COLOR_CONFIG_1, 0x170), +diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c +index 19161b6ab27fa..8574acefd40e7 100644 +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -303,16 +303,16 @@ static int vc4_plane_margins_adj(struct drm_plane_state *pstate) + adjhdisplay, + crtc_state->mode.hdisplay); + vc4_pstate->crtc_x += left; +- if (vc4_pstate->crtc_x > crtc_state->mode.hdisplay - left) +- vc4_pstate->crtc_x = crtc_state->mode.hdisplay - left; ++ if (vc4_pstate->crtc_x > crtc_state->mode.hdisplay - right) ++ vc4_pstate->crtc_x = crtc_state->mode.hdisplay - right; + + adjvdisplay = crtc_state->mode.vdisplay - (top + bottom); + vc4_pstate->crtc_y = DIV_ROUND_CLOSEST(vc4_pstate->crtc_y * + adjvdisplay, + crtc_state->mode.vdisplay); + vc4_pstate->crtc_y += top; +- if (vc4_pstate->crtc_y > crtc_state->mode.vdisplay - top) +- vc4_pstate->crtc_y = crtc_state->mode.vdisplay - top; ++ if (vc4_pstate->crtc_y > crtc_state->mode.vdisplay - bottom) ++ vc4_pstate->crtc_y = crtc_state->mode.vdisplay - bottom; + + vc4_pstate->crtc_w = DIV_ROUND_CLOSEST(vc4_pstate->crtc_w * + adjhdisplay, +@@ -332,7 +332,6 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) + struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); + struct drm_framebuffer *fb = state->fb; + struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); +- u32 subpixel_src_mask = (1 << 16) - 1; + int num_planes = fb->format->num_planes; + struct drm_crtc_state *crtc_state; + u32 h_subsample = fb->format->hsub; +@@ -354,18 +353,15 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) + for (i = 0; i < num_planes; i++) + vc4_state->offsets[i] = bo->paddr + fb->offsets[i]; + +- /* We don't support subpixel source positioning for scaling. */ +- if ((state->src.x1 & subpixel_src_mask) || +- (state->src.x2 & subpixel_src_mask) || +- (state->src.y1 & subpixel_src_mask) || +- (state->src.y2 & subpixel_src_mask)) { +- return -EINVAL; +- } +- +- vc4_state->src_x = state->src.x1 >> 16; +- vc4_state->src_y = state->src.y1 >> 16; +- vc4_state->src_w[0] = (state->src.x2 - state->src.x1) >> 16; +- vc4_state->src_h[0] = (state->src.y2 - state->src.y1) >> 16; ++ /* ++ * We don't support subpixel source positioning for scaling, ++ * but fractional coordinates can be generated by clipping ++ * so just round for now ++ */ ++ vc4_state->src_x = DIV_ROUND_CLOSEST(state->src.x1, 1 << 16); ++ vc4_state->src_y = DIV_ROUND_CLOSEST(state->src.y1, 1 << 16); ++ vc4_state->src_w[0] = DIV_ROUND_CLOSEST(state->src.x2, 1 << 16) - vc4_state->src_x; ++ vc4_state->src_h[0] = DIV_ROUND_CLOSEST(state->src.y2, 1 << 16) - vc4_state->src_y; + + vc4_state->crtc_x = state->dst.x1; + vc4_state->crtc_y = state->dst.y1; +diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c +index 5c1ad1596889b..15c3e63db396d 100644 +--- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c ++++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c +@@ -512,8 +512,10 @@ static int virtio_gpu_get_caps_ioctl(struct drm_device *dev, + spin_unlock(&vgdev->display_info_lock); + + /* not in cache - need to talk to hw */ +- virtio_gpu_cmd_get_capset(vgdev, found_valid, args->cap_set_ver, +- &cache_ent); ++ ret = virtio_gpu_cmd_get_capset(vgdev, found_valid, args->cap_set_ver, ++ &cache_ent); ++ if (ret) ++ return ret; + virtio_gpu_notify(vgdev); + + copy_exit: +diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c +index f648b0e24447b..9af9f355e0a77 100644 +--- a/drivers/gpu/drm/virtio/virtgpu_object.c ++++ b/drivers/gpu/drm/virtio/virtgpu_object.c +@@ -79,10 +79,10 @@ void virtio_gpu_cleanup_object(struct virtio_gpu_object *bo) + sg_free_table(shmem->pages); + kfree(shmem->pages); + shmem->pages = NULL; +- drm_gem_shmem_unpin(&bo->base.base); ++ drm_gem_shmem_unpin(&bo->base); + } + +- drm_gem_shmem_free_object(&bo->base.base); ++ drm_gem_shmem_free(&bo->base); + } else if (virtio_gpu_is_vram(bo)) { + struct virtio_gpu_object_vram *vram = to_virtio_gpu_vram(bo); + +@@ -116,15 +116,14 @@ static const struct drm_gem_object_funcs virtio_gpu_shmem_funcs = { + .free = virtio_gpu_free_object, + .open = virtio_gpu_gem_object_open, + .close = virtio_gpu_gem_object_close, +- +- .print_info = drm_gem_shmem_print_info, ++ .print_info = drm_gem_shmem_object_print_info, + .export = virtgpu_gem_prime_export, +- .pin = drm_gem_shmem_pin, +- .unpin = drm_gem_shmem_unpin, +- .get_sg_table = drm_gem_shmem_get_sg_table, +- .vmap = drm_gem_shmem_vmap, +- .vunmap = drm_gem_shmem_vunmap, +- .mmap = drm_gem_shmem_mmap, ++ .pin = drm_gem_shmem_object_pin, ++ .unpin = drm_gem_shmem_object_unpin, ++ .get_sg_table = drm_gem_shmem_object_get_sg_table, ++ .vmap = drm_gem_shmem_object_vmap, ++ .vunmap = drm_gem_shmem_object_vunmap, ++ .mmap = drm_gem_shmem_object_mmap, + }; + + bool virtio_gpu_is_shmem(struct virtio_gpu_object *bo) +@@ -157,7 +156,7 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev, + struct scatterlist *sg; + int si, ret; + +- ret = drm_gem_shmem_pin(&bo->base.base); ++ ret = drm_gem_shmem_pin(&bo->base); + if (ret < 0) + return -EINVAL; + +@@ -167,10 +166,10 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev, + * dma-ops. This is discouraged for other drivers, but should be fine + * since virtio_gpu doesn't support dma-buf import from other devices. + */ +- shmem->pages = drm_gem_shmem_get_sg_table(&bo->base.base); +- if (!shmem->pages) { +- drm_gem_shmem_unpin(&bo->base.base); +- return -EINVAL; ++ shmem->pages = drm_gem_shmem_get_sg_table(&bo->base); ++ if (IS_ERR(shmem->pages)) { ++ drm_gem_shmem_unpin(&bo->base); ++ return PTR_ERR(shmem->pages); + } + + if (use_dma_api) { +@@ -277,6 +276,6 @@ err_put_objs: + err_put_id: + virtio_gpu_resource_id_put(vgdev, bo->hw_res_handle); + err_free_gem: +- drm_gem_shmem_free_object(&shmem_obj->base); ++ drm_gem_shmem_free(shmem_obj); + return ret; + } +diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c +index 6284db50ec9bf..ab149b80f86c1 100644 +--- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c ++++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c +@@ -154,6 +154,8 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) + dev = &privdata->pdev->dev; + + cl_data->num_hid_devices = amd_mp2_get_sensor_num(privdata, &cl_data->sensor_idx[0]); ++ if (cl_data->num_hid_devices == 0) ++ return -ENODEV; + + INIT_DELAYED_WORK(&cl_data->work, amd_sfh_work); + INIT_DELAYED_WORK(&cl_data->work_buffer, amd_sfh_work_buffer); +diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_hid.c b/drivers/hid/amd-sfh-hid/amd_sfh_hid.c +index a4bda2ac713e9..3b0615c6aecff 100644 +--- a/drivers/hid/amd-sfh-hid/amd_sfh_hid.c ++++ b/drivers/hid/amd-sfh-hid/amd_sfh_hid.c +@@ -98,11 +98,15 @@ static int amdtp_wait_for_response(struct hid_device *hid) + + void amdtp_hid_wakeup(struct hid_device *hid) + { +- struct amdtp_hid_data *hid_data = hid->driver_data; +- struct amdtp_cl_data *cli_data = hid_data->cli_data; ++ struct amdtp_hid_data *hid_data; ++ struct amdtp_cl_data *cli_data; + +- cli_data->request_done[cli_data->cur_hid_dev] = true; +- wake_up_interruptible(&hid_data->hid_wait); ++ if (hid) { ++ hid_data = hid->driver_data; ++ cli_data = hid_data->cli_data; ++ cli_data->request_done[cli_data->cur_hid_dev] = true; ++ wake_up_interruptible(&hid_data->hid_wait); ++ } + } + + static struct hid_ll_driver amdtp_hid_ll_driver = { +diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c +index ae8f1f2536e94..13a4db42cd7a7 100644 +--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c ++++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c +@@ -323,7 +323,8 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i + rc = amd_sfh_hid_client_init(privdata); + if (rc) { + amd_sfh_clear_intr(privdata); +- dev_err(&pdev->dev, "amd_sfh_hid_client_init failed\n"); ++ if (rc != -EOPNOTSUPP) ++ dev_err(&pdev->dev, "amd_sfh_hid_client_init failed\n"); + return rc; + } + +diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c +index 2b986d0dbde46..db146d0f7937e 100644 +--- a/drivers/hid/hid-alps.c ++++ b/drivers/hid/hid-alps.c +@@ -830,6 +830,8 @@ static const struct hid_device_id alps_id[] = { + USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL) }, + { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, + USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1) }, ++ { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, ++ USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_UNICORN_LEGACY) }, + { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, + USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_T4_BTNLESS) }, + { } +diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c +index 477baa30889cc..172f20e88c6c9 100644 +--- a/drivers/hid/hid-cp2112.c ++++ b/drivers/hid/hid-cp2112.c +@@ -788,6 +788,11 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr, + data->word = le16_to_cpup((__le16 *)buf); + break; + case I2C_SMBUS_I2C_BLOCK_DATA: ++ if (read_length > I2C_SMBUS_BLOCK_MAX) { ++ ret = -EINVAL; ++ goto power_normal; ++ } ++ + memcpy(data->block + 1, buf, read_length); + break; + case I2C_SMBUS_BLOCK_DATA: +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 42b5b050b72d1..ceaa36fc429ef 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -398,6 +398,7 @@ + #define USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN 0x2544 + #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706 + #define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN 0x261A ++#define I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN 0x2A1C + + #define USB_VENDOR_ID_ELECOM 0x056e + #define USB_DEVICE_ID_ELECOM_BM084 0x0061 +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index 3172987a9ebd3..125043a28a35c 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -333,6 +333,8 @@ static const struct hid_device_id hid_battery_quirks[] = { + HID_BATTERY_QUIRK_IGNORE }, + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN), + HID_BATTERY_QUIRK_IGNORE }, ++ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN), ++ HID_BATTERY_QUIRK_IGNORE }, + {} + }; + +diff --git a/drivers/hid/hid-mcp2221.c b/drivers/hid/hid-mcp2221.c +index 4211b9839209b..de52e9f7bb8cb 100644 +--- a/drivers/hid/hid-mcp2221.c ++++ b/drivers/hid/hid-mcp2221.c +@@ -385,6 +385,9 @@ static int mcp_smbus_write(struct mcp2221 *mcp, u16 addr, + data_len = 7; + break; + default: ++ if (len > I2C_SMBUS_BLOCK_MAX) ++ return -EINVAL; ++ + memcpy(&mcp->txbuf[5], buf, len); + data_len = len + 5; + } +diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c +index b1bbf297f66b0..7e67c41d97a44 100644 +--- a/drivers/hid/wacom_sys.c ++++ b/drivers/hid/wacom_sys.c +@@ -2124,7 +2124,7 @@ static int wacom_register_inputs(struct wacom *wacom) + + error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac); + if (error) { +- /* no pad in use on this interface */ ++ /* no pad events using this interface */ + input_free_device(pad_input_dev); + wacom_wac->pad_input = NULL; + pad_input_dev = NULL; +diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c +index a7176fc0635dd..c454231afec89 100644 +--- a/drivers/hid/wacom_wac.c ++++ b/drivers/hid/wacom_wac.c +@@ -638,9 +638,26 @@ static int wacom_intuos_id_mangle(int tool_id) + return (tool_id & ~0xFFF) << 4 | (tool_id & 0xFFF); + } + ++static bool wacom_is_art_pen(int tool_id) ++{ ++ bool is_art_pen = false; ++ ++ switch (tool_id) { ++ case 0x885: /* Intuos3 Marker Pen */ ++ case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */ ++ case 0x10804: /* Intuos4/5 13HD/24HD Art Pen */ ++ is_art_pen = true; ++ break; ++ } ++ return is_art_pen; ++} ++ + static int wacom_intuos_get_tool_type(int tool_id) + { +- int tool_type; ++ int tool_type = BTN_TOOL_PEN; ++ ++ if (wacom_is_art_pen(tool_id)) ++ return tool_type; + + switch (tool_id) { + case 0x812: /* Inking pen */ +@@ -655,12 +672,9 @@ static int wacom_intuos_get_tool_type(int tool_id) + case 0x852: + case 0x823: /* Intuos3 Grip Pen */ + case 0x813: /* Intuos3 Classic Pen */ +- case 0x885: /* Intuos3 Marker Pen */ + case 0x802: /* Intuos4/5 13HD/24HD General Pen */ +- case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */ + case 0x8e2: /* IntuosHT2 pen */ + case 0x022: +- case 0x10804: /* Intuos4/5 13HD/24HD Art Pen */ + case 0x10842: /* MobileStudio Pro Pro Pen slim */ + case 0x14802: /* Intuos4/5 13HD/24HD Classic Pen */ + case 0x16802: /* Cintiq 13HD Pro Pen */ +@@ -718,10 +732,6 @@ static int wacom_intuos_get_tool_type(int tool_id) + case 0x10902: /* Intuos4/5 13HD/24HD Airbrush */ + tool_type = BTN_TOOL_AIRBRUSH; + break; +- +- default: /* Unknown tool */ +- tool_type = BTN_TOOL_PEN; +- break; + } + return tool_type; + } +@@ -2007,7 +2017,6 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, + wacom_wac->has_mute_touch_switch = true; + usage->type = EV_SW; + usage->code = SW_MUTE_DEVICE; +- features->device_type |= WACOM_DEVICETYPE_PAD; + break; + case WACOM_HID_WD_TOUCHSTRIP: + wacom_map_usage(input, usage, field, EV_ABS, ABS_RX, 0); +@@ -2087,6 +2096,30 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field + wacom_wac->hid_data.inrange_state |= value; + } + ++ /* Process touch switch state first since it is reported through touch interface, ++ * which is indepentent of pad interface. In the case when there are no other pad ++ * events, the pad interface will not even be created. ++ */ ++ if ((equivalent_usage == WACOM_HID_WD_MUTE_DEVICE) || ++ (equivalent_usage == WACOM_HID_WD_TOUCHONOFF)) { ++ if (wacom_wac->shared->touch_input) { ++ bool *is_touch_on = &wacom_wac->shared->is_touch_on; ++ ++ if (equivalent_usage == WACOM_HID_WD_MUTE_DEVICE && value) ++ *is_touch_on = !(*is_touch_on); ++ else if (equivalent_usage == WACOM_HID_WD_TOUCHONOFF) ++ *is_touch_on = value; ++ ++ input_report_switch(wacom_wac->shared->touch_input, ++ SW_MUTE_DEVICE, !(*is_touch_on)); ++ input_sync(wacom_wac->shared->touch_input); ++ } ++ return; ++ } ++ ++ if (!input) ++ return; ++ + switch (equivalent_usage) { + case WACOM_HID_WD_TOUCHRING: + /* +@@ -2122,22 +2155,6 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field + input_event(input, usage->type, usage->code, 0); + break; + +- case WACOM_HID_WD_MUTE_DEVICE: +- case WACOM_HID_WD_TOUCHONOFF: +- if (wacom_wac->shared->touch_input) { +- bool *is_touch_on = &wacom_wac->shared->is_touch_on; +- +- if (equivalent_usage == WACOM_HID_WD_MUTE_DEVICE && value) +- *is_touch_on = !(*is_touch_on); +- else if (equivalent_usage == WACOM_HID_WD_TOUCHONOFF) +- *is_touch_on = value; +- +- input_report_switch(wacom_wac->shared->touch_input, +- SW_MUTE_DEVICE, !(*is_touch_on)); +- input_sync(wacom_wac->shared->touch_input); +- } +- break; +- + case WACOM_HID_WD_MODE_CHANGE: + if (wacom_wac->is_direct_mode != value) { + wacom_wac->is_direct_mode = value; +@@ -2323,6 +2340,9 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field + } + return; + case HID_DG_TWIST: ++ /* don't modify the value if the pen doesn't support the feature */ ++ if (!wacom_is_art_pen(wacom_wac->id[0])) return; ++ + /* + * Userspace expects pen twist to have its zero point when + * the buttons/finger is on the tablet's left. HID values +@@ -2795,7 +2815,7 @@ void wacom_wac_event(struct hid_device *hdev, struct hid_field *field, + /* usage tests must precede field tests */ + if (WACOM_BATTERY_USAGE(usage)) + wacom_wac_battery_event(hdev, field, usage, value); +- else if (WACOM_PAD_FIELD(field) && wacom->wacom_wac.pad_input) ++ else if (WACOM_PAD_FIELD(field)) + wacom_wac_pad_event(hdev, field, usage, value); + else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input) + wacom_wac_pen_event(hdev, field, usage, value); +diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c +index 9cb1c3588038f..597cbb4391bdc 100644 +--- a/drivers/hwmon/dell-smm-hwmon.c ++++ b/drivers/hwmon/dell-smm-hwmon.c +@@ -1198,6 +1198,14 @@ static const struct dmi_system_id i8k_whitelist_fan_control[] __initconst = { + }, + .driver_data = (void *)&i8k_fan_control_data[I8K_FAN_34A3_35A3], + }, ++ { ++ .ident = "Dell XPS 13 7390", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "XPS 13 7390"), ++ }, ++ .driver_data = (void *)&i8k_fan_control_data[I8K_FAN_34A3_35A3], ++ }, + { } + }; + +diff --git a/drivers/hwmon/drivetemp.c b/drivers/hwmon/drivetemp.c +index 1eb37106a220b..5bac2b0fc7bb6 100644 +--- a/drivers/hwmon/drivetemp.c ++++ b/drivers/hwmon/drivetemp.c +@@ -621,3 +621,4 @@ module_exit(drivetemp_exit); + MODULE_AUTHOR("Guenter Roeck <linus@roeck-us.net>"); + MODULE_DESCRIPTION("Hard drive temperature monitor"); + MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:drivetemp"); +diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c +index 7f4a639597306..ae4d14257a11d 100644 +--- a/drivers/hwmon/sht15.c ++++ b/drivers/hwmon/sht15.c +@@ -1020,25 +1020,20 @@ err_release_reg: + static int sht15_remove(struct platform_device *pdev) + { + struct sht15_data *data = platform_get_drvdata(pdev); ++ int ret; + +- /* +- * Make sure any reads from the device are done and +- * prevent new ones beginning +- */ +- mutex_lock(&data->read_lock); +- if (sht15_soft_reset(data)) { +- mutex_unlock(&data->read_lock); +- return -EFAULT; +- } + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&pdev->dev.kobj, &sht15_attr_group); ++ ++ ret = sht15_soft_reset(data); ++ if (ret) ++ dev_err(&pdev->dev, "Failed to reset device (%pe)\n", ERR_PTR(ret)); ++ + if (!IS_ERR(data->reg)) { + regulator_unregister_notifier(data->reg, &data->nb); + regulator_disable(data->reg); + } + +- mutex_unlock(&data->read_lock); +- + return 0; + } + +diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c +index a6bdf4cf80ca1..6471f4232a2e0 100644 +--- a/drivers/hwtracing/coresight/coresight-core.c ++++ b/drivers/hwtracing/coresight/coresight-core.c +@@ -1427,6 +1427,7 @@ static int coresight_remove_match(struct device *dev, void *data) + * platform data. + */ + fwnode_handle_put(conn->child_fwnode); ++ conn->child_fwnode = NULL; + /* No need to continue */ + break; + } +diff --git a/drivers/hwtracing/intel_th/msu-sink.c b/drivers/hwtracing/intel_th/msu-sink.c +index 2c7f5116be126..891b28ea25fe6 100644 +--- a/drivers/hwtracing/intel_th/msu-sink.c ++++ b/drivers/hwtracing/intel_th/msu-sink.c +@@ -71,6 +71,9 @@ static int msu_sink_alloc_window(void *data, struct sg_table **sgt, size_t size) + block = dma_alloc_coherent(priv->dev->parent->parent, + PAGE_SIZE, &sg_dma_address(sg_ptr), + GFP_KERNEL); ++ if (!block) ++ return -ENOMEM; ++ + sg_set_buf(sg_ptr, block, PAGE_SIZE); + } + +diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c +index 432ade0842f68..d95d916b4682b 100644 +--- a/drivers/hwtracing/intel_th/msu.c ++++ b/drivers/hwtracing/intel_th/msu.c +@@ -1069,6 +1069,16 @@ msc_buffer_set_uc(struct msc *msc) {} + static inline void msc_buffer_set_wb(struct msc *msc) {} + #endif /* CONFIG_X86 */ + ++static struct page *msc_sg_page(struct scatterlist *sg) ++{ ++ void *addr = sg_virt(sg); ++ ++ if (is_vmalloc_addr(addr)) ++ return vmalloc_to_page(addr); ++ ++ return sg_page(sg); ++} ++ + /** + * msc_buffer_win_alloc() - alloc a window for a multiblock mode + * @msc: MSC device +@@ -1139,7 +1149,7 @@ static void __msc_buffer_win_free(struct msc *msc, struct msc_window *win) + int i; + + for_each_sg(win->sgt->sgl, sg, win->nr_segs, i) { +- struct page *page = sg_page(sg); ++ struct page *page = msc_sg_page(sg); + + page->mapping = NULL; + dma_free_coherent(msc_dev(win->msc)->parent->parent, PAGE_SIZE, +@@ -1403,7 +1413,7 @@ found: + pgoff -= win->pgoff; + + for_each_sg(win->sgt->sgl, sg, win->nr_segs, blk) { +- struct page *page = sg_page(sg); ++ struct page *page = msc_sg_page(sg); + size_t pgsz = PFN_DOWN(sg->length); + + if (pgoff < pgsz) +diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c +index 7da4f298ed01e..147d338c191e7 100644 +--- a/drivers/hwtracing/intel_th/pci.c ++++ b/drivers/hwtracing/intel_th/pci.c +@@ -100,8 +100,10 @@ static int intel_th_pci_probe(struct pci_dev *pdev, + } + + th = intel_th_alloc(&pdev->dev, drvdata, resource, r); +- if (IS_ERR(th)) +- return PTR_ERR(th); ++ if (IS_ERR(th)) { ++ err = PTR_ERR(th); ++ goto err_free_irq; ++ } + + th->activate = intel_th_pci_activate; + th->deactivate = intel_th_pci_deactivate; +@@ -109,6 +111,10 @@ static int intel_th_pci_probe(struct pci_dev *pdev, + pci_set_master(pdev); + + return 0; ++ ++err_free_irq: ++ pci_free_irq_vectors(pdev); ++ return err; + } + + static void intel_th_pci_remove(struct pci_dev *pdev) +@@ -278,6 +284,21 @@ static const struct pci_device_id intel_th_pci_id_table[] = { + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x54a6), + .driver_data = (kernel_ulong_t)&intel_th_2x, + }, ++ { ++ /* Meteor Lake-P */ ++ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7e24), ++ .driver_data = (kernel_ulong_t)&intel_th_2x, ++ }, ++ { ++ /* Raptor Lake-S */ ++ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7a26), ++ .driver_data = (kernel_ulong_t)&intel_th_2x, ++ }, ++ { ++ /* Raptor Lake-S CPU */ ++ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa76f), ++ .driver_data = (kernel_ulong_t)&intel_th_2x, ++ }, + { + /* Alder Lake CPU */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x466f), +diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c +index 630cfa4ddd468..33f5588a50c07 100644 +--- a/drivers/i2c/busses/i2c-cadence.c ++++ b/drivers/i2c/busses/i2c-cadence.c +@@ -573,8 +573,13 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id) + ctrl_reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET); + ctrl_reg |= CDNS_I2C_CR_RW | CDNS_I2C_CR_CLR_FIFO; + ++ /* ++ * Receive up to I2C_SMBUS_BLOCK_MAX data bytes, plus one message length ++ * byte, plus one checksum byte if PEC is enabled. p_msg->len will be 2 if ++ * PEC is enabled, otherwise 1. ++ */ + if (id->p_msg->flags & I2C_M_RECV_LEN) +- id->recv_count = I2C_SMBUS_BLOCK_MAX + 1; ++ id->recv_count = I2C_SMBUS_BLOCK_MAX + id->p_msg->len; + + id->curr_recv_count = id->recv_count; + +@@ -789,6 +794,9 @@ static int cdns_i2c_process_msg(struct cdns_i2c *id, struct i2c_msg *msg, + if (id->err_status & CDNS_I2C_IXR_ARB_LOST) + return -EAGAIN; + ++ if (msg->flags & I2C_M_RECV_LEN) ++ msg->len += min_t(unsigned int, msg->buf[0], I2C_SMBUS_BLOCK_MAX); ++ + return 0; + } + +diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c +index 864a3f1bd4e14..68f67d084c63a 100644 +--- a/drivers/i2c/busses/i2c-mxs.c ++++ b/drivers/i2c/busses/i2c-mxs.c +@@ -799,7 +799,7 @@ static int mxs_i2c_probe(struct platform_device *pdev) + if (!i2c) + return -ENOMEM; + +- i2c->dev_type = (enum mxs_i2c_devtype)of_device_get_match_data(&pdev->dev); ++ i2c->dev_type = (uintptr_t)of_device_get_match_data(&pdev->dev); + + i2c->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(i2c->regs)) +diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c +index d9ac62c1ac25e..31e3d2c9d6bc5 100644 +--- a/drivers/i2c/busses/i2c-npcm7xx.c ++++ b/drivers/i2c/busses/i2c-npcm7xx.c +@@ -123,11 +123,11 @@ enum i2c_addr { + * Since the addr regs are sprinkled all over the address space, + * use this array to get the address or each register. + */ +-#define I2C_NUM_OWN_ADDR 10 ++#define I2C_NUM_OWN_ADDR 2 ++#define I2C_NUM_OWN_ADDR_SUPPORTED 2 ++ + static const int npcm_i2caddr[I2C_NUM_OWN_ADDR] = { +- NPCM_I2CADDR1, NPCM_I2CADDR2, NPCM_I2CADDR3, NPCM_I2CADDR4, +- NPCM_I2CADDR5, NPCM_I2CADDR6, NPCM_I2CADDR7, NPCM_I2CADDR8, +- NPCM_I2CADDR9, NPCM_I2CADDR10, ++ NPCM_I2CADDR1, NPCM_I2CADDR2, + }; + #endif + +@@ -391,14 +391,10 @@ static void npcm_i2c_disable(struct npcm_i2c *bus) + #if IS_ENABLED(CONFIG_I2C_SLAVE) + int i; + +- /* select bank 0 for I2C addresses */ +- npcm_i2c_select_bank(bus, I2C_BANK_0); +- + /* Slave addresses removal */ +- for (i = I2C_SLAVE_ADDR1; i < I2C_NUM_OWN_ADDR; i++) ++ for (i = I2C_SLAVE_ADDR1; i < I2C_NUM_OWN_ADDR_SUPPORTED; i++) + iowrite8(0, bus->reg + npcm_i2caddr[i]); + +- npcm_i2c_select_bank(bus, I2C_BANK_1); + #endif + /* Disable module */ + i2cctl2 = ioread8(bus->reg + NPCM_I2CCTL2); +@@ -603,8 +599,7 @@ static int npcm_i2c_slave_enable(struct npcm_i2c *bus, enum i2c_addr addr_type, + i2cctl1 &= ~NPCM_I2CCTL1_GCMEN; + iowrite8(i2cctl1, bus->reg + NPCM_I2CCTL1); + return 0; +- } +- if (addr_type == I2C_ARP_ADDR) { ++ } else if (addr_type == I2C_ARP_ADDR) { + i2cctl3 = ioread8(bus->reg + NPCM_I2CCTL3); + if (enable) + i2cctl3 |= I2CCTL3_ARPMEN; +@@ -613,16 +608,16 @@ static int npcm_i2c_slave_enable(struct npcm_i2c *bus, enum i2c_addr addr_type, + iowrite8(i2cctl3, bus->reg + NPCM_I2CCTL3); + return 0; + } ++ if (addr_type > I2C_SLAVE_ADDR2 && addr_type <= I2C_SLAVE_ADDR10) ++ dev_err(bus->dev, "try to enable more than 2 SA not supported\n"); ++ + if (addr_type >= I2C_ARP_ADDR) + return -EFAULT; +- /* select bank 0 for address 3 to 10 */ +- if (addr_type > I2C_SLAVE_ADDR2) +- npcm_i2c_select_bank(bus, I2C_BANK_0); ++ + /* Set and enable the address */ + iowrite8(sa_reg, bus->reg + npcm_i2caddr[addr_type]); + npcm_i2c_slave_int_enable(bus, enable); +- if (addr_type > I2C_SLAVE_ADDR2) +- npcm_i2c_select_bank(bus, I2C_BANK_1); ++ + return 0; + } + #endif +@@ -843,15 +838,11 @@ static u8 npcm_i2c_get_slave_addr(struct npcm_i2c *bus, enum i2c_addr addr_type) + { + u8 slave_add; + +- /* select bank 0 for address 3 to 10 */ +- if (addr_type > I2C_SLAVE_ADDR2) +- npcm_i2c_select_bank(bus, I2C_BANK_0); ++ if (addr_type > I2C_SLAVE_ADDR2 && addr_type <= I2C_SLAVE_ADDR10) ++ dev_err(bus->dev, "get slave: try to use more than 2 SA not supported\n"); + + slave_add = ioread8(bus->reg + npcm_i2caddr[(int)addr_type]); + +- if (addr_type > I2C_SLAVE_ADDR2) +- npcm_i2c_select_bank(bus, I2C_BANK_1); +- + return slave_add; + } + +@@ -861,12 +852,12 @@ static int npcm_i2c_remove_slave_addr(struct npcm_i2c *bus, u8 slave_add) + + /* Set the enable bit */ + slave_add |= 0x80; +- npcm_i2c_select_bank(bus, I2C_BANK_0); +- for (i = I2C_SLAVE_ADDR1; i < I2C_NUM_OWN_ADDR; i++) { ++ ++ for (i = I2C_SLAVE_ADDR1; i < I2C_NUM_OWN_ADDR_SUPPORTED; i++) { + if (ioread8(bus->reg + npcm_i2caddr[i]) == slave_add) + iowrite8(0, bus->reg + npcm_i2caddr[i]); + } +- npcm_i2c_select_bank(bus, I2C_BANK_1); ++ + return 0; + } + +@@ -921,11 +912,15 @@ static int npcm_i2c_slave_get_wr_buf(struct npcm_i2c *bus) + for (i = 0; i < I2C_HW_FIFO_SIZE; i++) { + if (bus->slv_wr_size >= I2C_HW_FIFO_SIZE) + break; +- i2c_slave_event(bus->slave, I2C_SLAVE_READ_REQUESTED, &value); ++ if (bus->state == I2C_SLAVE_MATCH) { ++ i2c_slave_event(bus->slave, I2C_SLAVE_READ_REQUESTED, &value); ++ bus->state = I2C_OPER_STARTED; ++ } else { ++ i2c_slave_event(bus->slave, I2C_SLAVE_READ_PROCESSED, &value); ++ } + ind = (bus->slv_wr_ind + bus->slv_wr_size) % I2C_HW_FIFO_SIZE; + bus->slv_wr_buf[ind] = value; + bus->slv_wr_size++; +- i2c_slave_event(bus->slave, I2C_SLAVE_READ_PROCESSED, &value); + } + return I2C_HW_FIFO_SIZE - ret; + } +@@ -973,7 +968,6 @@ static void npcm_i2c_slave_xmit(struct npcm_i2c *bus, u16 nwrite, + if (nwrite == 0) + return; + +- bus->state = I2C_OPER_STARTED; + bus->operation = I2C_WRITE_OPER; + + /* get the next buffer */ +diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c +index cfbef70e8ba70..8fb065caf30b4 100644 +--- a/drivers/i2c/i2c-core-base.c ++++ b/drivers/i2c/i2c-core-base.c +@@ -2464,8 +2464,9 @@ void i2c_put_adapter(struct i2c_adapter *adap) + if (!adap) + return; + +- put_device(&adap->dev); + module_put(adap->owner); ++ /* Should be last, otherwise we risk use-after-free with 'adap' */ ++ put_device(&adap->dev); + } + EXPORT_SYMBOL(i2c_put_adapter); + +diff --git a/drivers/i2c/muxes/i2c-mux-gpmux.c b/drivers/i2c/muxes/i2c-mux-gpmux.c +index d3acd8d66c323..33024acaac02b 100644 +--- a/drivers/i2c/muxes/i2c-mux-gpmux.c ++++ b/drivers/i2c/muxes/i2c-mux-gpmux.c +@@ -134,6 +134,7 @@ static int i2c_mux_probe(struct platform_device *pdev) + return 0; + + err_children: ++ of_node_put(child); + i2c_mux_del_adapters(muxc); + err_parent: + i2c_put_adapter(parent); +diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h +index 5ad10db9819fe..416090c6b1e81 100644 +--- a/drivers/iio/accel/bma400.h ++++ b/drivers/iio/accel/bma400.h +@@ -83,8 +83,27 @@ + #define BMA400_ACC_ODR_MIN_WHOLE_HZ 25 + #define BMA400_ACC_ODR_MIN_HZ 12 + +-#define BMA400_SCALE_MIN 38357 +-#define BMA400_SCALE_MAX 306864 ++/* ++ * BMA400_SCALE_MIN macro value represents m/s^2 for 1 LSB before ++ * converting to micro values for +-2g range. ++ * ++ * For +-2g - 1 LSB = 0.976562 milli g = 0.009576 m/s^2 ++ * For +-4g - 1 LSB = 1.953125 milli g = 0.019153 m/s^2 ++ * For +-16g - 1 LSB = 7.8125 milli g = 0.076614 m/s^2 ++ * ++ * The raw value which is used to select the different ranges is determined ++ * by the first bit set position from the scale value, so BMA400_SCALE_MIN ++ * should be odd. ++ * ++ * Scale values for +-2g, +-4g, +-8g and +-16g are populated into bma400_scales ++ * array by left shifting BMA400_SCALE_MIN. ++ * e.g.: ++ * To select +-2g = 9577 << 0 = raw value to write is 0. ++ * To select +-8g = 9577 << 2 = raw value to write is 2. ++ * To select +-16g = 9577 << 3 = raw value to write is 3. ++ */ ++#define BMA400_SCALE_MIN 9577 ++#define BMA400_SCALE_MAX 76617 + + #define BMA400_NUM_REGULATORS 2 + #define BMA400_VDD_REGULATOR 0 +diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c +index 21520e022a212..7e65985346504 100644 +--- a/drivers/iio/accel/bma400_core.c ++++ b/drivers/iio/accel/bma400_core.c +@@ -13,14 +13,14 @@ + + #include <linux/bitops.h> + #include <linux/device.h> +-#include <linux/iio/iio.h> +-#include <linux/iio/sysfs.h> + #include <linux/kernel.h> + #include <linux/module.h> + #include <linux/mutex.h> + #include <linux/regmap.h> + #include <linux/regulator/consumer.h> + ++#include <linux/iio/iio.h> ++ + #include "bma400.h" + + /* +diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c b/drivers/iio/accel/cros_ec_accel_legacy.c +index b6f3471b62dcf..3b77fded2dc07 100644 +--- a/drivers/iio/accel/cros_ec_accel_legacy.c ++++ b/drivers/iio/accel/cros_ec_accel_legacy.c +@@ -215,7 +215,7 @@ static int cros_ec_accel_legacy_probe(struct platform_device *pdev) + return -ENOMEM; + + ret = cros_ec_sensors_core_init(pdev, indio_dev, true, +- cros_ec_sensors_capture, NULL); ++ cros_ec_sensors_capture); + if (ret) + return ret; + +@@ -235,7 +235,7 @@ static int cros_ec_accel_legacy_probe(struct platform_device *pdev) + state->sign[CROS_EC_SENSOR_Z] = -1; + } + +- return devm_iio_device_register(dev, indio_dev); ++ return cros_ec_sensors_core_register(dev, indio_dev, NULL); + } + + static struct platform_driver cros_ec_accel_platform_driver = { +diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c b/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c +index af801e203623e..02d3cf36acb0c 100644 +--- a/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c ++++ b/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c +@@ -97,7 +97,7 @@ static int cros_ec_lid_angle_probe(struct platform_device *pdev) + if (!indio_dev) + return -ENOMEM; + +- ret = cros_ec_sensors_core_init(pdev, indio_dev, false, NULL, NULL); ++ ret = cros_ec_sensors_core_init(pdev, indio_dev, false, NULL); + if (ret) + return ret; + +@@ -113,7 +113,7 @@ static int cros_ec_lid_angle_probe(struct platform_device *pdev) + if (ret) + return ret; + +- return devm_iio_device_register(dev, indio_dev); ++ return cros_ec_sensors_core_register(dev, indio_dev, NULL); + } + + static const struct platform_device_id cros_ec_lid_angle_ids[] = { +diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +index 376a5b30010ae..5cce34fdff022 100644 +--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c ++++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +@@ -235,8 +235,7 @@ static int cros_ec_sensors_probe(struct platform_device *pdev) + return -ENOMEM; + + ret = cros_ec_sensors_core_init(pdev, indio_dev, true, +- cros_ec_sensors_capture, +- cros_ec_sensors_push_data); ++ cros_ec_sensors_capture); + if (ret) + return ret; + +@@ -297,7 +296,8 @@ static int cros_ec_sensors_probe(struct platform_device *pdev) + else + state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd; + +- return devm_iio_device_register(dev, indio_dev); ++ return cros_ec_sensors_core_register(dev, indio_dev, ++ cros_ec_sensors_push_data); + } + + static const struct platform_device_id cros_ec_sensors_ids[] = { +diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +index 28bde13003b74..b0c1dc8cc4c52 100644 +--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c ++++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +@@ -234,21 +234,18 @@ static void cros_ec_sensors_core_clean(void *arg) + + /** + * cros_ec_sensors_core_init() - basic initialization of the core structure +- * @pdev: platform device created for the sensors ++ * @pdev: platform device created for the sensor + * @indio_dev: iio device structure of the device + * @physical_device: true if the device refers to a physical device + * @trigger_capture: function pointer to call buffer is triggered, + * for backward compatibility. +- * @push_data: function to call when cros_ec_sensorhub receives +- * a sample for that sensor. + * + * Return: 0 on success, -errno on failure. + */ + int cros_ec_sensors_core_init(struct platform_device *pdev, + struct iio_dev *indio_dev, + bool physical_device, +- cros_ec_sensors_capture_t trigger_capture, +- cros_ec_sensorhub_push_data_cb_t push_data) ++ cros_ec_sensors_capture_t trigger_capture) + { + struct device *dev = &pdev->dev; + struct cros_ec_sensors_core_state *state = iio_priv(indio_dev); +@@ -339,17 +336,6 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, + if (ret) + return ret; + +- ret = cros_ec_sensorhub_register_push_data( +- sensor_hub, sensor_platform->sensor_num, +- indio_dev, push_data); +- if (ret) +- return ret; +- +- ret = devm_add_action_or_reset( +- dev, cros_ec_sensors_core_clean, pdev); +- if (ret) +- return ret; +- + /* Timestamp coming from FIFO are in ns since boot. */ + ret = iio_device_set_clock(indio_dev, CLOCK_BOOTTIME); + if (ret) +@@ -371,6 +357,46 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, + } + EXPORT_SYMBOL_GPL(cros_ec_sensors_core_init); + ++/** ++ * cros_ec_sensors_core_register() - Register callback to FIFO and IIO when ++ * sensor is ready. ++ * It must be called at the end of the sensor probe routine. ++ * @dev: device created for the sensor ++ * @indio_dev: iio device structure of the device ++ * @push_data: function to call when cros_ec_sensorhub receives ++ * a sample for that sensor. ++ * ++ * Return: 0 on success, -errno on failure. ++ */ ++int cros_ec_sensors_core_register(struct device *dev, ++ struct iio_dev *indio_dev, ++ cros_ec_sensorhub_push_data_cb_t push_data) ++{ ++ struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev); ++ struct cros_ec_sensorhub *sensor_hub = dev_get_drvdata(dev->parent); ++ struct platform_device *pdev = to_platform_device(dev); ++ struct cros_ec_dev *ec = sensor_hub->ec; ++ int ret; ++ ++ ret = devm_iio_device_register(dev, indio_dev); ++ if (ret) ++ return ret; ++ ++ if (!push_data || ++ !cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) ++ return 0; ++ ++ ret = cros_ec_sensorhub_register_push_data( ++ sensor_hub, sensor_platform->sensor_num, ++ indio_dev, push_data); ++ if (ret) ++ return ret; ++ ++ return devm_add_action_or_reset( ++ dev, cros_ec_sensors_core_clean, pdev); ++} ++EXPORT_SYMBOL_GPL(cros_ec_sensors_core_register); ++ + /** + * cros_ec_motion_send_host_cmd() - send motion sense host command + * @state: pointer to state information for device +diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c +index f282e9cc34c53..6aee6c989485e 100644 +--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c ++++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c +@@ -261,6 +261,7 @@ int inv_mpu_magn_set_rate(const struct inv_mpu6050_state *st, int fifo_rate) + */ + int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st) + { ++ struct device *dev = regmap_get_device(st->map); + const char *orient; + char *str; + int i; +@@ -279,22 +280,27 @@ int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st) + st->magn_orient.rotation[4] = st->orientation.rotation[1]; + st->magn_orient.rotation[5] = st->orientation.rotation[2]; + /* z <- -z */ +- for (i = 0; i < 3; ++i) { +- orient = st->orientation.rotation[6 + i]; +- /* use length + 2 for adding minus sign if needed */ +- str = devm_kzalloc(regmap_get_device(st->map), +- strlen(orient) + 2, GFP_KERNEL); +- if (str == NULL) ++ for (i = 6; i < 9; ++i) { ++ orient = st->orientation.rotation[i]; ++ ++ /* ++ * The value is negated according to one of the following ++ * rules: ++ * ++ * 1) Drop leading minus. ++ * 2) Leave 0 as is. ++ * 3) Add leading minus. ++ */ ++ if (orient[0] == '-') ++ str = devm_kstrdup(dev, orient + 1, GFP_KERNEL); ++ else if (!strcmp(orient, "0")) ++ str = devm_kstrdup(dev, orient, GFP_KERNEL); ++ else ++ str = devm_kasprintf(dev, GFP_KERNEL, "-%s", orient); ++ if (!str) + return -ENOMEM; +- if (strcmp(orient, "0") == 0) { +- strcpy(str, orient); +- } else if (orient[0] == '-') { +- strcpy(str, &orient[1]); +- } else { +- str[0] = '-'; +- strcpy(&str[1], orient); +- } +- st->magn_orient.rotation[6 + i] = str; ++ ++ st->magn_orient.rotation[i] = str; + } + break; + default: +diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c +index 3e1e86d987cc2..a7f5d432c95d9 100644 +--- a/drivers/iio/industrialio-core.c ++++ b/drivers/iio/industrialio-core.c +@@ -818,7 +818,23 @@ static ssize_t iio_format_avail_list(char *buf, const int *vals, + + static ssize_t iio_format_avail_range(char *buf, const int *vals, int type) + { +- return iio_format_list(buf, vals, type, 3, "[", "]"); ++ int length; ++ ++ /* ++ * length refers to the array size , not the number of elements. ++ * The purpose is to print the range [min , step ,max] so length should ++ * be 3 in case of int, and 6 for other types. ++ */ ++ switch (type) { ++ case IIO_VAL_INT: ++ length = 3; ++ break; ++ default: ++ length = 6; ++ break; ++ } ++ ++ return iio_format_list(buf, vals, type, length, "[", "]"); + } + + static ssize_t iio_read_channel_info_avail(struct device *dev, +diff --git a/drivers/iio/light/cros_ec_light_prox.c b/drivers/iio/light/cros_ec_light_prox.c +index de472f23d1cba..16b893bae3881 100644 +--- a/drivers/iio/light/cros_ec_light_prox.c ++++ b/drivers/iio/light/cros_ec_light_prox.c +@@ -181,8 +181,7 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev) + return -ENOMEM; + + ret = cros_ec_sensors_core_init(pdev, indio_dev, true, +- cros_ec_sensors_capture, +- cros_ec_sensors_push_data); ++ cros_ec_sensors_capture); + if (ret) + return ret; + +@@ -240,7 +239,8 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev) + + state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd; + +- return devm_iio_device_register(dev, indio_dev); ++ return cros_ec_sensors_core_register(dev, indio_dev, ++ cros_ec_sensors_push_data); + } + + static const struct platform_device_id cros_ec_light_prox_ids[] = { +diff --git a/drivers/iio/light/isl29028.c b/drivers/iio/light/isl29028.c +index 9de3262aa6883..a62787f5d5e7b 100644 +--- a/drivers/iio/light/isl29028.c ++++ b/drivers/iio/light/isl29028.c +@@ -625,7 +625,7 @@ static int isl29028_probe(struct i2c_client *client, + ISL29028_POWER_OFF_DELAY_MS); + pm_runtime_use_autosuspend(&client->dev); + +- ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev); ++ ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, + "%s(): iio registration failed with error %d\n", +diff --git a/drivers/iio/pressure/cros_ec_baro.c b/drivers/iio/pressure/cros_ec_baro.c +index 2f882e1094232..0511edbf868d7 100644 +--- a/drivers/iio/pressure/cros_ec_baro.c ++++ b/drivers/iio/pressure/cros_ec_baro.c +@@ -138,8 +138,7 @@ static int cros_ec_baro_probe(struct platform_device *pdev) + return -ENOMEM; + + ret = cros_ec_sensors_core_init(pdev, indio_dev, true, +- cros_ec_sensors_capture, +- cros_ec_sensors_push_data); ++ cros_ec_sensors_capture); + if (ret) + return ret; + +@@ -186,7 +185,8 @@ static int cros_ec_baro_probe(struct platform_device *pdev) + + state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd; + +- return devm_iio_device_register(dev, indio_dev); ++ return cros_ec_sensors_core_register(dev, indio_dev, ++ cros_ec_sensors_push_data); + } + + static const struct platform_device_id cros_ec_baro_ids[] = { +diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c +index 3ebdd42fec362..686d170a5947e 100644 +--- a/drivers/infiniband/hw/hfi1/file_ops.c ++++ b/drivers/infiniband/hw/hfi1/file_ops.c +@@ -1179,8 +1179,10 @@ static int setup_base_ctxt(struct hfi1_filedata *fd, + goto done; + + ret = init_user_ctxt(fd, uctxt); +- if (ret) ++ if (ret) { ++ hfi1_free_ctxt_rcv_groups(uctxt); + goto done; ++ } + + user_init(uctxt); + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index bf01210c56c23..1dbad159f3792 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -5854,8 +5854,8 @@ static irqreturn_t hns_roce_v2_msix_interrupt_abn(int irq, void *dev_id) + + dev_err(dev, "AEQ overflow!\n"); + +- int_st |= 1 << HNS_ROCE_V2_VF_INT_ST_AEQ_OVERFLOW_S; +- roce_write(hr_dev, ROCEE_VF_ABN_INT_ST_REG, int_st); ++ roce_write(hr_dev, ROCEE_VF_ABN_INT_ST_REG, ++ 1 << HNS_ROCE_V2_VF_INT_ST_AEQ_OVERFLOW_S); + + /* Set reset level for reset_event() */ + if (ops->set_default_reset_request) +diff --git a/drivers/infiniband/hw/irdma/cm.c b/drivers/infiniband/hw/irdma/cm.c +index 60d4e9c151ff7..b08c67bb264c9 100644 +--- a/drivers/infiniband/hw/irdma/cm.c ++++ b/drivers/infiniband/hw/irdma/cm.c +@@ -1477,12 +1477,13 @@ irdma_find_listener(struct irdma_cm_core *cm_core, u32 *dst_addr, u16 dst_port, + list_for_each_entry (listen_node, &cm_core->listen_list, list) { + memcpy(listen_addr, listen_node->loc_addr, sizeof(listen_addr)); + listen_port = listen_node->loc_port; ++ if (listen_port != dst_port || ++ !(listener_state & listen_node->listener_state)) ++ continue; + /* compare node pair, return node handle if a match */ +- if ((!memcmp(listen_addr, dst_addr, sizeof(listen_addr)) || +- !memcmp(listen_addr, ip_zero, sizeof(listen_addr))) && +- listen_port == dst_port && +- vlan_id == listen_node->vlan_id && +- (listener_state & listen_node->listener_state)) { ++ if (!memcmp(listen_addr, ip_zero, sizeof(listen_addr)) || ++ (!memcmp(listen_addr, dst_addr, sizeof(listen_addr)) && ++ vlan_id == listen_node->vlan_id)) { + refcount_inc(&listen_node->refcnt); + spin_unlock_irqrestore(&cm_core->listen_list_lock, + flags); +diff --git a/drivers/infiniband/hw/irdma/hw.c b/drivers/infiniband/hw/irdma/hw.c +index 4f763e552eae8..3d5d3f8d5ded8 100644 +--- a/drivers/infiniband/hw/irdma/hw.c ++++ b/drivers/infiniband/hw/irdma/hw.c +@@ -257,10 +257,6 @@ static void irdma_process_aeq(struct irdma_pci_f *rf) + iwqp->last_aeq = info->ae_id; + spin_unlock_irqrestore(&iwqp->lock, flags); + ctx_info = &iwqp->ctx_info; +- if (rdma_protocol_roce(&iwqp->iwdev->ibdev, 1)) +- ctx_info->roce_info->err_rq_idx_valid = true; +- else +- ctx_info->iwarp_info->err_rq_idx_valid = true; + } else { + if (info->ae_id != IRDMA_AE_CQ_OPERATION_ERROR) + continue; +@@ -370,16 +366,12 @@ static void irdma_process_aeq(struct irdma_pci_f *rf) + case IRDMA_AE_LCE_FUNCTION_CATASTROPHIC: + case IRDMA_AE_LCE_CQ_CATASTROPHIC: + case IRDMA_AE_UDA_XMIT_DGRAM_TOO_LONG: +- if (rdma_protocol_roce(&iwdev->ibdev, 1)) +- ctx_info->roce_info->err_rq_idx_valid = false; +- else +- ctx_info->iwarp_info->err_rq_idx_valid = false; +- fallthrough; + default: + ibdev_err(&iwdev->ibdev, "abnormal ae_id = 0x%x bool qp=%d qp_id = %d\n", + info->ae_id, info->qp, info->qp_cq_id); + if (rdma_protocol_roce(&iwdev->ibdev, 1)) { +- if (!info->sq && ctx_info->roce_info->err_rq_idx_valid) { ++ ctx_info->roce_info->err_rq_idx_valid = info->rq; ++ if (info->rq) { + ctx_info->roce_info->err_rq_idx = info->wqe_idx; + irdma_sc_qp_setctx_roce(&iwqp->sc_qp, iwqp->host_ctx.va, + ctx_info); +@@ -388,7 +380,8 @@ static void irdma_process_aeq(struct irdma_pci_f *rf) + irdma_cm_disconn(iwqp); + break; + } +- if (!info->sq && ctx_info->iwarp_info->err_rq_idx_valid) { ++ ctx_info->iwarp_info->err_rq_idx_valid = info->rq; ++ if (info->rq) { + ctx_info->iwarp_info->err_rq_idx = info->wqe_idx; + ctx_info->tcp_info_valid = false; + ctx_info->iwarp_info_valid = true; +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index 0eef464286913..cac4fb228b9b0 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -1759,11 +1759,11 @@ static int irdma_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata) + spin_unlock_irqrestore(&iwcq->lock, flags); + + irdma_cq_wq_destroy(iwdev->rf, cq); +- irdma_cq_free_rsrc(iwdev->rf, iwcq); + + spin_lock_irqsave(&iwceq->ce_lock, flags); + irdma_sc_cleanup_ceqes(cq, ceq); + spin_unlock_irqrestore(&iwceq->ce_lock, flags); ++ irdma_cq_free_rsrc(iwdev->rf, iwcq); + + return 0; + } +diff --git a/drivers/infiniband/hw/mlx5/fs.c b/drivers/infiniband/hw/mlx5/fs.c +index 5fbc0a8454b91..8a7e182af5303 100644 +--- a/drivers/infiniband/hw/mlx5/fs.c ++++ b/drivers/infiniband/hw/mlx5/fs.c +@@ -2078,12 +2078,10 @@ static int mlx5_ib_matcher_ns(struct uverbs_attr_bundle *attrs, + if (err) + return err; + +- if (flags) { +- mlx5_ib_ft_type_to_namespace( ++ if (flags) ++ return mlx5_ib_ft_type_to_namespace( + MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX, + &obj->ns_type); +- return 0; +- } + } + + obj->ns_type = MLX5_FLOW_NAMESPACE_BYPASS; +diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c +index 49dfedbc56651..bb0c2b93a34d8 100644 +--- a/drivers/infiniband/hw/qedr/verbs.c ++++ b/drivers/infiniband/hw/qedr/verbs.c +@@ -3093,7 +3093,7 @@ static struct qedr_mr *__qedr_alloc_mr(struct ib_pd *ibpd, + else + DP_ERR(dev, "roce alloc tid returned error %d\n", rc); + +- goto err0; ++ goto err1; + } + + /* Index only, 18 bit long, lkey = itid << 8 | key */ +@@ -3117,7 +3117,7 @@ static struct qedr_mr *__qedr_alloc_mr(struct ib_pd *ibpd, + rc = dev->ops->rdma_register_tid(dev->rdma_ctx, &mr->hw_mr); + if (rc) { + DP_ERR(dev, "roce register tid returned an error %d\n", rc); +- goto err1; ++ goto err2; + } + + mr->ibmr.lkey = mr->hw_mr.itid << 8 | mr->hw_mr.key; +@@ -3126,8 +3126,10 @@ static struct qedr_mr *__qedr_alloc_mr(struct ib_pd *ibpd, + DP_DEBUG(dev, QEDR_MSG_MR, "alloc frmr: %x\n", mr->ibmr.lkey); + return mr; + +-err1: ++err2: + dev->ops->rdma_free_tid(dev->rdma_ctx, mr->hw_mr.itid); ++err1: ++ qedr_free_pbl(dev, &mr->info.pbl_info, mr->info.pbl_table); + err0: + kfree(mr); + return ERR_PTR(rc); +diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c +index d2d802c776fdc..48a3864ada29a 100644 +--- a/drivers/infiniband/sw/rxe/rxe_comp.c ++++ b/drivers/infiniband/sw/rxe/rxe_comp.c +@@ -142,10 +142,7 @@ static inline enum comp_state get_wqe(struct rxe_qp *qp, + /* we come here whether or not we found a response packet to see if + * there are any posted WQEs + */ +- if (qp->is_user) +- wqe = queue_head(qp->sq.queue, QUEUE_TYPE_FROM_USER); +- else +- wqe = queue_head(qp->sq.queue, QUEUE_TYPE_KERNEL); ++ wqe = queue_head(qp->sq.queue, QUEUE_TYPE_FROM_CLIENT); + *wqe_p = wqe; + + /* no WQE or requester has not started it yet */ +@@ -432,10 +429,7 @@ static void do_complete(struct rxe_qp *qp, struct rxe_send_wqe *wqe) + if (post) + make_send_cqe(qp, wqe, &cqe); + +- if (qp->is_user) +- advance_consumer(qp->sq.queue, QUEUE_TYPE_FROM_USER); +- else +- advance_consumer(qp->sq.queue, QUEUE_TYPE_KERNEL); ++ queue_advance_consumer(qp->sq.queue, QUEUE_TYPE_FROM_CLIENT); + + if (post) + rxe_cq_post(qp->scq, &cqe, 0); +@@ -539,7 +533,7 @@ static void rxe_drain_resp_pkts(struct rxe_qp *qp, bool notify) + wqe->status = IB_WC_WR_FLUSH_ERR; + do_complete(qp, wqe); + } else { +- advance_consumer(q, q->type); ++ queue_advance_consumer(q, q->type); + } + } + } +diff --git a/drivers/infiniband/sw/rxe/rxe_cq.c b/drivers/infiniband/sw/rxe/rxe_cq.c +index aef288f164fdd..4eedaa0244b39 100644 +--- a/drivers/infiniband/sw/rxe/rxe_cq.c ++++ b/drivers/infiniband/sw/rxe/rxe_cq.c +@@ -25,11 +25,7 @@ int rxe_cq_chk_attr(struct rxe_dev *rxe, struct rxe_cq *cq, + } + + if (cq) { +- if (cq->is_user) +- count = queue_count(cq->queue, QUEUE_TYPE_TO_USER); +- else +- count = queue_count(cq->queue, QUEUE_TYPE_KERNEL); +- ++ count = queue_count(cq->queue, QUEUE_TYPE_TO_CLIENT); + if (cqe < count) { + pr_warn("cqe(%d) < current # elements in queue (%d)", + cqe, count); +@@ -65,7 +61,7 @@ int rxe_cq_from_init(struct rxe_dev *rxe, struct rxe_cq *cq, int cqe, + int err; + enum queue_type type; + +- type = uresp ? QUEUE_TYPE_TO_USER : QUEUE_TYPE_KERNEL; ++ type = QUEUE_TYPE_TO_CLIENT; + cq->queue = rxe_queue_init(rxe, &cqe, + sizeof(struct rxe_cqe), type); + if (!cq->queue) { +@@ -117,11 +113,7 @@ int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited) + + spin_lock_irqsave(&cq->cq_lock, flags); + +- if (cq->is_user) +- full = queue_full(cq->queue, QUEUE_TYPE_TO_USER); +- else +- full = queue_full(cq->queue, QUEUE_TYPE_KERNEL); +- ++ full = queue_full(cq->queue, QUEUE_TYPE_TO_CLIENT); + if (unlikely(full)) { + spin_unlock_irqrestore(&cq->cq_lock, flags); + if (cq->ibcq.event_handler) { +@@ -134,17 +126,10 @@ int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited) + return -EBUSY; + } + +- if (cq->is_user) +- addr = producer_addr(cq->queue, QUEUE_TYPE_TO_USER); +- else +- addr = producer_addr(cq->queue, QUEUE_TYPE_KERNEL); +- ++ addr = queue_producer_addr(cq->queue, QUEUE_TYPE_TO_CLIENT); + memcpy(addr, cqe, sizeof(*cqe)); + +- if (cq->is_user) +- advance_producer(cq->queue, QUEUE_TYPE_TO_USER); +- else +- advance_producer(cq->queue, QUEUE_TYPE_KERNEL); ++ queue_advance_producer(cq->queue, QUEUE_TYPE_TO_CLIENT); + + spin_unlock_irqrestore(&cq->cq_lock, flags); + +diff --git a/drivers/infiniband/sw/rxe/rxe_loc.h b/drivers/infiniband/sw/rxe/rxe_loc.h +index 4fd73b51fabf2..21bd969718bd7 100644 +--- a/drivers/infiniband/sw/rxe/rxe_loc.h ++++ b/drivers/infiniband/sw/rxe/rxe_loc.h +@@ -85,7 +85,7 @@ struct rxe_mr *lookup_mr(struct rxe_pd *pd, int access, u32 key, + enum rxe_mr_lookup_type type); + int mr_check_range(struct rxe_mr *mr, u64 iova, size_t length); + int advance_dma_data(struct rxe_dma_info *dma, unsigned int length); +-int rxe_invalidate_mr(struct rxe_qp *qp, u32 rkey); ++int rxe_invalidate_mr(struct rxe_qp *qp, u32 key); + int rxe_reg_fast_mr(struct rxe_qp *qp, struct rxe_send_wqe *wqe); + int rxe_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata); + void rxe_mr_cleanup(struct rxe_pool_entry *arg); +diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c +index bedcf15aaea75..7c2e7b291b653 100644 +--- a/drivers/infiniband/sw/rxe/rxe_mr.c ++++ b/drivers/infiniband/sw/rxe/rxe_mr.c +@@ -522,22 +522,22 @@ struct rxe_mr *lookup_mr(struct rxe_pd *pd, int access, u32 key, + return mr; + } + +-int rxe_invalidate_mr(struct rxe_qp *qp, u32 rkey) ++int rxe_invalidate_mr(struct rxe_qp *qp, u32 key) + { + struct rxe_dev *rxe = to_rdev(qp->ibqp.device); + struct rxe_mr *mr; + int ret; + +- mr = rxe_pool_get_index(&rxe->mr_pool, rkey >> 8); ++ mr = rxe_pool_get_index(&rxe->mr_pool, key >> 8); + if (!mr) { +- pr_err("%s: No MR for rkey %#x\n", __func__, rkey); ++ pr_err("%s: No MR for key %#x\n", __func__, key); + ret = -EINVAL; + goto err; + } + +- if (rkey != mr->rkey) { +- pr_err("%s: rkey (%#x) doesn't match mr->rkey (%#x)\n", +- __func__, rkey, mr->rkey); ++ if (mr->rkey ? (key != mr->rkey) : (key != mr->lkey)) { ++ pr_err("%s: wr key (%#x) doesn't match mr key (%#x)\n", ++ __func__, key, (mr->rkey ? mr->rkey : mr->lkey)); + ret = -EINVAL; + goto err_drop_ref; + } +diff --git a/drivers/infiniband/sw/rxe/rxe_mw.c b/drivers/infiniband/sw/rxe/rxe_mw.c +index a5e2ea7d80f02..933a0b29275b9 100644 +--- a/drivers/infiniband/sw/rxe/rxe_mw.c ++++ b/drivers/infiniband/sw/rxe/rxe_mw.c +@@ -71,8 +71,6 @@ int rxe_dealloc_mw(struct ib_mw *ibmw) + static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe, + struct rxe_mw *mw, struct rxe_mr *mr) + { +- u32 key = wqe->wr.wr.mw.rkey & 0xff; +- + if (mw->ibmw.type == IB_MW_TYPE_1) { + if (unlikely(mw->state != RXE_MW_STATE_VALID)) { + pr_err_once( +@@ -110,11 +108,6 @@ static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe, + } + } + +- if (unlikely(key == (mw->rkey & 0xff))) { +- pr_err_once("attempt to bind MW with same key\n"); +- return -EINVAL; +- } +- + /* remaining checks only apply to a nonzero MR */ + if (!mr) + return 0; +diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c +index ed326d82725cd..661b83d65af32 100644 +--- a/drivers/infiniband/sw/rxe/rxe_qp.c ++++ b/drivers/infiniband/sw/rxe/rxe_qp.c +@@ -195,6 +195,14 @@ static void rxe_qp_init_misc(struct rxe_dev *rxe, struct rxe_qp *qp, + spin_lock_init(&qp->grp_lock); + spin_lock_init(&qp->state_lock); + ++ spin_lock_init(&qp->req.task.state_lock); ++ spin_lock_init(&qp->resp.task.state_lock); ++ spin_lock_init(&qp->comp.task.state_lock); ++ ++ spin_lock_init(&qp->sq.sq_lock); ++ spin_lock_init(&qp->rq.producer_lock); ++ spin_lock_init(&qp->rq.consumer_lock); ++ + atomic_set(&qp->ssn, 0); + atomic_set(&qp->skb_out, 0); + } +@@ -231,7 +239,7 @@ static int rxe_qp_init_req(struct rxe_dev *rxe, struct rxe_qp *qp, + qp->sq.max_inline = init->cap.max_inline_data = wqe_size; + wqe_size += sizeof(struct rxe_send_wqe); + +- type = uresp ? QUEUE_TYPE_FROM_USER : QUEUE_TYPE_KERNEL; ++ type = QUEUE_TYPE_FROM_CLIENT; + qp->sq.queue = rxe_queue_init(rxe, &qp->sq.max_wr, + wqe_size, type); + if (!qp->sq.queue) +@@ -248,18 +256,13 @@ static int rxe_qp_init_req(struct rxe_dev *rxe, struct rxe_qp *qp, + return err; + } + +- if (qp->is_user) +- qp->req.wqe_index = producer_index(qp->sq.queue, +- QUEUE_TYPE_FROM_USER); +- else +- qp->req.wqe_index = producer_index(qp->sq.queue, +- QUEUE_TYPE_KERNEL); ++ qp->req.wqe_index = queue_get_producer(qp->sq.queue, ++ QUEUE_TYPE_FROM_CLIENT); + + qp->req.state = QP_STATE_RESET; + qp->req.opcode = -1; + qp->comp.opcode = -1; + +- spin_lock_init(&qp->sq.sq_lock); + skb_queue_head_init(&qp->req_pkts); + + rxe_init_task(rxe, &qp->req.task, qp, +@@ -293,7 +296,7 @@ static int rxe_qp_init_resp(struct rxe_dev *rxe, struct rxe_qp *qp, + pr_debug("qp#%d max_wr = %d, max_sge = %d, wqe_size = %d\n", + qp_num(qp), qp->rq.max_wr, qp->rq.max_sge, wqe_size); + +- type = uresp ? QUEUE_TYPE_FROM_USER : QUEUE_TYPE_KERNEL; ++ type = QUEUE_TYPE_FROM_CLIENT; + qp->rq.queue = rxe_queue_init(rxe, &qp->rq.max_wr, + wqe_size, type); + if (!qp->rq.queue) +@@ -310,11 +313,6 @@ static int rxe_qp_init_resp(struct rxe_dev *rxe, struct rxe_qp *qp, + } + } + +- spin_lock_init(&qp->rq.producer_lock); +- spin_lock_init(&qp->rq.consumer_lock); +- +- qp->rq.is_user = qp->is_user; +- + skb_queue_head_init(&qp->resp_pkts); + + rxe_init_task(rxe, &qp->resp.task, qp, +diff --git a/drivers/infiniband/sw/rxe/rxe_queue.c b/drivers/infiniband/sw/rxe/rxe_queue.c +index 72d95398e6041..6e6e023c1b45d 100644 +--- a/drivers/infiniband/sw/rxe/rxe_queue.c ++++ b/drivers/infiniband/sw/rxe/rxe_queue.c +@@ -111,17 +111,33 @@ err1: + static int resize_finish(struct rxe_queue *q, struct rxe_queue *new_q, + unsigned int num_elem) + { +- if (!queue_empty(q, q->type) && (num_elem < queue_count(q, q->type))) ++ enum queue_type type = q->type; ++ u32 prod; ++ u32 cons; ++ ++ if (!queue_empty(q, q->type) && (num_elem < queue_count(q, type))) + return -EINVAL; + +- while (!queue_empty(q, q->type)) { +- memcpy(producer_addr(new_q, new_q->type), +- consumer_addr(q, q->type), +- new_q->elem_size); +- advance_producer(new_q, new_q->type); +- advance_consumer(q, q->type); ++ prod = queue_get_producer(new_q, type); ++ cons = queue_get_consumer(q, type); ++ ++ while (!queue_empty(q, type)) { ++ memcpy(queue_addr_from_index(new_q, prod), ++ queue_addr_from_index(q, cons), new_q->elem_size); ++ prod = queue_next_index(new_q, prod); ++ cons = queue_next_index(q, cons); + } + ++ new_q->buf->producer_index = prod; ++ q->buf->consumer_index = cons; ++ ++ /* update private index copies */ ++ if (type == QUEUE_TYPE_TO_CLIENT) ++ new_q->index = new_q->buf->producer_index; ++ else ++ q->index = q->buf->consumer_index; ++ ++ /* exchange rxe_queue headers */ + swap(*q, *new_q); + + return 0; +diff --git a/drivers/infiniband/sw/rxe/rxe_queue.h b/drivers/infiniband/sw/rxe/rxe_queue.h +index 2702b0e55fc33..6227112ef7a2f 100644 +--- a/drivers/infiniband/sw/rxe/rxe_queue.h ++++ b/drivers/infiniband/sw/rxe/rxe_queue.h +@@ -10,34 +10,47 @@ + /* for definition of shared struct rxe_queue_buf */ + #include <uapi/rdma/rdma_user_rxe.h> + +-/* implements a simple circular buffer that can optionally be +- * shared between user space and the kernel and can be resized +- * the requested element size is rounded up to a power of 2 +- * and the number of elements in the buffer is also rounded +- * up to a power of 2. Since the queue is empty when the +- * producer and consumer indices match the maximum capacity +- * of the queue is one less than the number of element slots ++/* Implements a simple circular buffer that is shared between user ++ * and the driver and can be resized. The requested element size is ++ * rounded up to a power of 2 and the number of elements in the buffer ++ * is also rounded up to a power of 2. Since the queue is empty when ++ * the producer and consumer indices match the maximum capacity of the ++ * queue is one less than the number of element slots. + * + * Notes: +- * - Kernel space indices are always masked off to q->index_mask +- * before storing so do not need to be checked on reads. +- * - User space indices may be out of range and must be +- * masked before use when read. +- * - The kernel indices for shared queues must not be written +- * by user space so a local copy is used and a shared copy is +- * stored when the local copy changes. ++ * - The driver indices are always masked off to q->index_mask ++ * before storing so do not need to be checked on reads. ++ * - The user whether user space or kernel is generally ++ * not trusted so its parameters are masked to make sure ++ * they do not access the queue out of bounds on reads. ++ * - The driver indices for queues must not be written ++ * by user so a local copy is used and a shared copy is ++ * stored when the local copy is changed. + * - By passing the type in the parameter list separate from q +- * the compiler can eliminate the switch statement when the +- * actual queue type is known when the function is called. +- * In the performance path this is done. In less critical +- * paths just q->type is passed. ++ * the compiler can eliminate the switch statement when the ++ * actual queue type is known when the function is called at ++ * compile time. ++ * - These queues are lock free. The user and driver must protect ++ * changes to their end of the queues with locks if more than one ++ * CPU can be accessing it at the same time. + */ + +-/* type of queue */ ++/** ++ * enum queue_type - type of queue ++ * @QUEUE_TYPE_TO_CLIENT: Queue is written by rxe driver and ++ * read by client. Used by rxe driver only. ++ * @QUEUE_TYPE_FROM_CLIENT: Queue is written by client and ++ * read by rxe driver. Used by rxe driver only. ++ * @QUEUE_TYPE_TO_DRIVER: Queue is written by client and ++ * read by rxe driver. Used by kernel client only. ++ * @QUEUE_TYPE_FROM_DRIVER: Queue is written by rxe driver and ++ * read by client. Used by kernel client only. ++ */ + enum queue_type { +- QUEUE_TYPE_KERNEL, +- QUEUE_TYPE_TO_USER, +- QUEUE_TYPE_FROM_USER, ++ QUEUE_TYPE_TO_CLIENT, ++ QUEUE_TYPE_FROM_CLIENT, ++ QUEUE_TYPE_TO_DRIVER, ++ QUEUE_TYPE_FROM_DRIVER, + }; + + struct rxe_queue { +@@ -69,238 +82,171 @@ struct rxe_queue *rxe_queue_init(struct rxe_dev *rxe, int *num_elem, + int rxe_queue_resize(struct rxe_queue *q, unsigned int *num_elem_p, + unsigned int elem_size, struct ib_udata *udata, + struct mminfo __user *outbuf, +- /* Protect producers while resizing queue */ +- spinlock_t *producer_lock, +- /* Protect consumers while resizing queue */ +- spinlock_t *consumer_lock); ++ spinlock_t *producer_lock, spinlock_t *consumer_lock); + + void rxe_queue_cleanup(struct rxe_queue *queue); + +-static inline int next_index(struct rxe_queue *q, int index) ++static inline u32 queue_next_index(struct rxe_queue *q, int index) + { +- return (index + 1) & q->buf->index_mask; ++ return (index + 1) & q->index_mask; + } + +-static inline int queue_empty(struct rxe_queue *q, enum queue_type type) ++static inline u32 queue_get_producer(const struct rxe_queue *q, ++ enum queue_type type) + { + u32 prod; +- u32 cons; + + switch (type) { +- case QUEUE_TYPE_FROM_USER: +- /* protect user space index */ ++ case QUEUE_TYPE_FROM_CLIENT: ++ /* protect user index */ + prod = smp_load_acquire(&q->buf->producer_index); +- cons = q->index; + break; +- case QUEUE_TYPE_TO_USER: ++ case QUEUE_TYPE_TO_CLIENT: + prod = q->index; +- /* protect user space index */ +- cons = smp_load_acquire(&q->buf->consumer_index); + break; +- case QUEUE_TYPE_KERNEL: ++ case QUEUE_TYPE_FROM_DRIVER: ++ /* protect driver index */ ++ prod = smp_load_acquire(&q->buf->producer_index); ++ break; ++ case QUEUE_TYPE_TO_DRIVER: + prod = q->buf->producer_index; +- cons = q->buf->consumer_index; + break; + } + +- return ((prod - cons) & q->index_mask) == 0; ++ return prod; + } + +-static inline int queue_full(struct rxe_queue *q, enum queue_type type) ++static inline u32 queue_get_consumer(const struct rxe_queue *q, ++ enum queue_type type) + { +- u32 prod; + u32 cons; + + switch (type) { +- case QUEUE_TYPE_FROM_USER: +- /* protect user space index */ +- prod = smp_load_acquire(&q->buf->producer_index); ++ case QUEUE_TYPE_FROM_CLIENT: + cons = q->index; + break; +- case QUEUE_TYPE_TO_USER: +- prod = q->index; +- /* protect user space index */ ++ case QUEUE_TYPE_TO_CLIENT: ++ /* protect user index */ + cons = smp_load_acquire(&q->buf->consumer_index); + break; +- case QUEUE_TYPE_KERNEL: +- prod = q->buf->producer_index; ++ case QUEUE_TYPE_FROM_DRIVER: + cons = q->buf->consumer_index; + break; ++ case QUEUE_TYPE_TO_DRIVER: ++ /* protect driver index */ ++ cons = smp_load_acquire(&q->buf->consumer_index); ++ break; + } + +- return ((prod + 1 - cons) & q->index_mask) == 0; ++ return cons; + } + +-static inline unsigned int queue_count(const struct rxe_queue *q, +- enum queue_type type) ++static inline int queue_empty(struct rxe_queue *q, enum queue_type type) + { +- u32 prod; +- u32 cons; +- +- switch (type) { +- case QUEUE_TYPE_FROM_USER: +- /* protect user space index */ +- prod = smp_load_acquire(&q->buf->producer_index); +- cons = q->index; +- break; +- case QUEUE_TYPE_TO_USER: +- prod = q->index; +- /* protect user space index */ +- cons = smp_load_acquire(&q->buf->consumer_index); +- break; +- case QUEUE_TYPE_KERNEL: +- prod = q->buf->producer_index; +- cons = q->buf->consumer_index; +- break; +- } ++ u32 prod = queue_get_producer(q, type); ++ u32 cons = queue_get_consumer(q, type); + +- return (prod - cons) & q->index_mask; ++ return ((prod - cons) & q->index_mask) == 0; + } + +-static inline void advance_producer(struct rxe_queue *q, enum queue_type type) ++static inline int queue_full(struct rxe_queue *q, enum queue_type type) + { +- u32 prod; ++ u32 prod = queue_get_producer(q, type); ++ u32 cons = queue_get_consumer(q, type); + +- switch (type) { +- case QUEUE_TYPE_FROM_USER: +- pr_warn_once("Normally kernel should not write user space index\n"); +- /* protect user space index */ +- prod = smp_load_acquire(&q->buf->producer_index); +- prod = (prod + 1) & q->index_mask; +- /* same */ +- smp_store_release(&q->buf->producer_index, prod); +- break; +- case QUEUE_TYPE_TO_USER: +- prod = q->index; +- q->index = (prod + 1) & q->index_mask; +- q->buf->producer_index = q->index; +- break; +- case QUEUE_TYPE_KERNEL: +- prod = q->buf->producer_index; +- q->buf->producer_index = (prod + 1) & q->index_mask; +- break; +- } ++ return ((prod + 1 - cons) & q->index_mask) == 0; + } + +-static inline void advance_consumer(struct rxe_queue *q, enum queue_type type) ++static inline u32 queue_count(const struct rxe_queue *q, ++ enum queue_type type) + { +- u32 cons; ++ u32 prod = queue_get_producer(q, type); ++ u32 cons = queue_get_consumer(q, type); + +- switch (type) { +- case QUEUE_TYPE_FROM_USER: +- cons = q->index; +- q->index = (cons + 1) & q->index_mask; +- q->buf->consumer_index = q->index; +- break; +- case QUEUE_TYPE_TO_USER: +- pr_warn_once("Normally kernel should not write user space index\n"); +- /* protect user space index */ +- cons = smp_load_acquire(&q->buf->consumer_index); +- cons = (cons + 1) & q->index_mask; +- /* same */ +- smp_store_release(&q->buf->consumer_index, cons); +- break; +- case QUEUE_TYPE_KERNEL: +- cons = q->buf->consumer_index; +- q->buf->consumer_index = (cons + 1) & q->index_mask; +- break; +- } ++ return (prod - cons) & q->index_mask; + } + +-static inline void *producer_addr(struct rxe_queue *q, enum queue_type type) ++static inline void queue_advance_producer(struct rxe_queue *q, ++ enum queue_type type) + { + u32 prod; + + switch (type) { +- case QUEUE_TYPE_FROM_USER: +- /* protect user space index */ +- prod = smp_load_acquire(&q->buf->producer_index); +- prod &= q->index_mask; ++ case QUEUE_TYPE_FROM_CLIENT: ++ pr_warn("%s: attempt to advance client index\n", ++ __func__); + break; +- case QUEUE_TYPE_TO_USER: ++ case QUEUE_TYPE_TO_CLIENT: + prod = q->index; ++ prod = (prod + 1) & q->index_mask; ++ q->index = prod; ++ /* protect user index */ ++ smp_store_release(&q->buf->producer_index, prod); ++ break; ++ case QUEUE_TYPE_FROM_DRIVER: ++ pr_warn("%s: attempt to advance driver index\n", ++ __func__); + break; +- case QUEUE_TYPE_KERNEL: ++ case QUEUE_TYPE_TO_DRIVER: + prod = q->buf->producer_index; ++ prod = (prod + 1) & q->index_mask; ++ q->buf->producer_index = prod; + break; + } +- +- return q->buf->data + (prod << q->log2_elem_size); + } + +-static inline void *consumer_addr(struct rxe_queue *q, enum queue_type type) ++static inline void queue_advance_consumer(struct rxe_queue *q, ++ enum queue_type type) + { + u32 cons; + + switch (type) { +- case QUEUE_TYPE_FROM_USER: ++ case QUEUE_TYPE_FROM_CLIENT: + cons = q->index; ++ cons = (cons + 1) & q->index_mask; ++ q->index = cons; ++ /* protect user index */ ++ smp_store_release(&q->buf->consumer_index, cons); + break; +- case QUEUE_TYPE_TO_USER: +- /* protect user space index */ +- cons = smp_load_acquire(&q->buf->consumer_index); +- cons &= q->index_mask; ++ case QUEUE_TYPE_TO_CLIENT: ++ pr_warn("%s: attempt to advance client index\n", ++ __func__); + break; +- case QUEUE_TYPE_KERNEL: ++ case QUEUE_TYPE_FROM_DRIVER: + cons = q->buf->consumer_index; ++ cons = (cons + 1) & q->index_mask; ++ q->buf->consumer_index = cons; ++ break; ++ case QUEUE_TYPE_TO_DRIVER: ++ pr_warn("%s: attempt to advance driver index\n", ++ __func__); + break; + } +- +- return q->buf->data + (cons << q->log2_elem_size); + } + +-static inline unsigned int producer_index(struct rxe_queue *q, +- enum queue_type type) ++static inline void *queue_producer_addr(struct rxe_queue *q, ++ enum queue_type type) + { +- u32 prod; ++ u32 prod = queue_get_producer(q, type); + +- switch (type) { +- case QUEUE_TYPE_FROM_USER: +- /* protect user space index */ +- prod = smp_load_acquire(&q->buf->producer_index); +- prod &= q->index_mask; +- break; +- case QUEUE_TYPE_TO_USER: +- prod = q->index; +- break; +- case QUEUE_TYPE_KERNEL: +- prod = q->buf->producer_index; +- break; +- } +- +- return prod; ++ return q->buf->data + (prod << q->log2_elem_size); + } + +-static inline unsigned int consumer_index(struct rxe_queue *q, +- enum queue_type type) ++static inline void *queue_consumer_addr(struct rxe_queue *q, ++ enum queue_type type) + { +- u32 cons; +- +- switch (type) { +- case QUEUE_TYPE_FROM_USER: +- cons = q->index; +- break; +- case QUEUE_TYPE_TO_USER: +- /* protect user space index */ +- cons = smp_load_acquire(&q->buf->consumer_index); +- cons &= q->index_mask; +- break; +- case QUEUE_TYPE_KERNEL: +- cons = q->buf->consumer_index; +- break; +- } ++ u32 cons = queue_get_consumer(q, type); + +- return cons; ++ return q->buf->data + (cons << q->log2_elem_size); + } + +-static inline void *addr_from_index(struct rxe_queue *q, +- unsigned int index) ++static inline void *queue_addr_from_index(struct rxe_queue *q, u32 index) + { + return q->buf->data + ((index & q->index_mask) +- << q->buf->log2_elem_size); ++ << q->log2_elem_size); + } + +-static inline unsigned int index_from_addr(const struct rxe_queue *q, ++static inline u32 queue_index_from_addr(const struct rxe_queue *q, + const void *addr) + { + return (((u8 *)addr - q->buf->data) >> q->log2_elem_size) +@@ -309,7 +255,7 @@ static inline unsigned int index_from_addr(const struct rxe_queue *q, + + static inline void *queue_head(struct rxe_queue *q, enum queue_type type) + { +- return queue_empty(q, type) ? NULL : consumer_addr(q, type); ++ return queue_empty(q, type) ? NULL : queue_consumer_addr(q, type); + } + + #endif /* RXE_QUEUE_H */ +diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c +index 7812e3d6a6c27..8c0e7ecd41414 100644 +--- a/drivers/infiniband/sw/rxe/rxe_req.c ++++ b/drivers/infiniband/sw/rxe/rxe_req.c +@@ -49,21 +49,16 @@ static void req_retry(struct rxe_qp *qp) + unsigned int cons; + unsigned int prod; + +- if (qp->is_user) { +- cons = consumer_index(q, QUEUE_TYPE_FROM_USER); +- prod = producer_index(q, QUEUE_TYPE_FROM_USER); +- } else { +- cons = consumer_index(q, QUEUE_TYPE_KERNEL); +- prod = producer_index(q, QUEUE_TYPE_KERNEL); +- } ++ cons = queue_get_consumer(q, QUEUE_TYPE_FROM_CLIENT); ++ prod = queue_get_producer(q, QUEUE_TYPE_FROM_CLIENT); + + qp->req.wqe_index = cons; + qp->req.psn = qp->comp.psn; + qp->req.opcode = -1; + + for (wqe_index = cons; wqe_index != prod; +- wqe_index = next_index(q, wqe_index)) { +- wqe = addr_from_index(qp->sq.queue, wqe_index); ++ wqe_index = queue_next_index(q, wqe_index)) { ++ wqe = queue_addr_from_index(qp->sq.queue, wqe_index); + mask = wr_opcode_mask(wqe->wr.opcode, qp); + + if (wqe->state == wqe_state_posted) +@@ -121,15 +116,9 @@ static struct rxe_send_wqe *req_next_wqe(struct rxe_qp *qp) + unsigned int cons; + unsigned int prod; + +- if (qp->is_user) { +- wqe = queue_head(q, QUEUE_TYPE_FROM_USER); +- cons = consumer_index(q, QUEUE_TYPE_FROM_USER); +- prod = producer_index(q, QUEUE_TYPE_FROM_USER); +- } else { +- wqe = queue_head(q, QUEUE_TYPE_KERNEL); +- cons = consumer_index(q, QUEUE_TYPE_KERNEL); +- prod = producer_index(q, QUEUE_TYPE_KERNEL); +- } ++ wqe = queue_head(q, QUEUE_TYPE_FROM_CLIENT); ++ cons = queue_get_consumer(q, QUEUE_TYPE_FROM_CLIENT); ++ prod = queue_get_producer(q, QUEUE_TYPE_FROM_CLIENT); + + if (unlikely(qp->req.state == QP_STATE_DRAIN)) { + /* check to see if we are drained; +@@ -170,7 +159,7 @@ static struct rxe_send_wqe *req_next_wqe(struct rxe_qp *qp) + if (index == prod) + return NULL; + +- wqe = addr_from_index(q, index); ++ wqe = queue_addr_from_index(q, index); + + if (unlikely((qp->req.state == QP_STATE_DRAIN || + qp->req.state == QP_STATE_DRAINED) && +@@ -560,7 +549,8 @@ static void update_state(struct rxe_qp *qp, struct rxe_send_wqe *wqe, + qp->req.opcode = pkt->opcode; + + if (pkt->mask & RXE_END_MASK) +- qp->req.wqe_index = next_index(qp->sq.queue, qp->req.wqe_index); ++ qp->req.wqe_index = queue_next_index(qp->sq.queue, ++ qp->req.wqe_index); + + qp->need_req_skb = 0; + +@@ -610,11 +600,13 @@ static int rxe_do_local_ops(struct rxe_qp *qp, struct rxe_send_wqe *wqe) + + wqe->state = wqe_state_done; + wqe->status = IB_WC_SUCCESS; +- qp->req.wqe_index = next_index(qp->sq.queue, qp->req.wqe_index); ++ qp->req.wqe_index = queue_next_index(qp->sq.queue, qp->req.wqe_index); + +- if ((wqe->wr.send_flags & IB_SEND_SIGNALED) || +- qp->sq_sig_type == IB_SIGNAL_ALL_WR) +- rxe_run_task(&qp->comp.task, 1); ++ /* There is no ack coming for local work requests ++ * which can lead to a deadlock. So go ahead and complete ++ * it now. ++ */ ++ rxe_run_task(&qp->comp.task, 1); + + return 0; + } +@@ -641,7 +633,8 @@ next_wqe: + goto exit; + + if (unlikely(qp->req.state == QP_STATE_RESET)) { +- qp->req.wqe_index = consumer_index(q, q->type); ++ qp->req.wqe_index = queue_get_consumer(q, ++ QUEUE_TYPE_FROM_CLIENT); + qp->req.opcode = -1; + qp->req.need_rd_atomic = 0; + qp->req.wait_psn = 0; +@@ -707,7 +700,7 @@ next_wqe: + wqe->last_psn = qp->req.psn; + qp->req.psn = (qp->req.psn + 1) & BTH_PSN_MASK; + qp->req.opcode = IB_OPCODE_UD_SEND_ONLY; +- qp->req.wqe_index = next_index(qp->sq.queue, ++ qp->req.wqe_index = queue_next_index(qp->sq.queue, + qp->req.wqe_index); + wqe->state = wqe_state_done; + wqe->status = IB_WC_SUCCESS; +diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c +index 8ed172ab0beb4..e7dec84810614 100644 +--- a/drivers/infiniband/sw/rxe/rxe_resp.c ++++ b/drivers/infiniband/sw/rxe/rxe_resp.c +@@ -303,10 +303,7 @@ static enum resp_states get_srq_wqe(struct rxe_qp *qp) + + spin_lock_bh(&srq->rq.consumer_lock); + +- if (qp->is_user) +- wqe = queue_head(q, QUEUE_TYPE_FROM_USER); +- else +- wqe = queue_head(q, QUEUE_TYPE_KERNEL); ++ wqe = queue_head(q, QUEUE_TYPE_FROM_CLIENT); + if (!wqe) { + spin_unlock_bh(&srq->rq.consumer_lock); + return RESPST_ERR_RNR; +@@ -322,13 +319,8 @@ static enum resp_states get_srq_wqe(struct rxe_qp *qp) + memcpy(&qp->resp.srq_wqe, wqe, size); + + qp->resp.wqe = &qp->resp.srq_wqe.wqe; +- if (qp->is_user) { +- advance_consumer(q, QUEUE_TYPE_FROM_USER); +- count = queue_count(q, QUEUE_TYPE_FROM_USER); +- } else { +- advance_consumer(q, QUEUE_TYPE_KERNEL); +- count = queue_count(q, QUEUE_TYPE_KERNEL); +- } ++ queue_advance_consumer(q, QUEUE_TYPE_FROM_CLIENT); ++ count = queue_count(q, QUEUE_TYPE_FROM_CLIENT); + + if (srq->limit && srq->ibsrq.event_handler && (count < srq->limit)) { + srq->limit = 0; +@@ -357,12 +349,8 @@ static enum resp_states check_resource(struct rxe_qp *qp, + qp->resp.status = IB_WC_WR_FLUSH_ERR; + return RESPST_COMPLETE; + } else if (!srq) { +- if (qp->is_user) +- qp->resp.wqe = queue_head(qp->rq.queue, +- QUEUE_TYPE_FROM_USER); +- else +- qp->resp.wqe = queue_head(qp->rq.queue, +- QUEUE_TYPE_KERNEL); ++ qp->resp.wqe = queue_head(qp->rq.queue, ++ QUEUE_TYPE_FROM_CLIENT); + if (qp->resp.wqe) { + qp->resp.status = IB_WC_WR_FLUSH_ERR; + return RESPST_COMPLETE; +@@ -389,12 +377,8 @@ static enum resp_states check_resource(struct rxe_qp *qp, + if (srq) + return get_srq_wqe(qp); + +- if (qp->is_user) +- qp->resp.wqe = queue_head(qp->rq.queue, +- QUEUE_TYPE_FROM_USER); +- else +- qp->resp.wqe = queue_head(qp->rq.queue, +- QUEUE_TYPE_KERNEL); ++ qp->resp.wqe = queue_head(qp->rq.queue, ++ QUEUE_TYPE_FROM_CLIENT); + return (qp->resp.wqe) ? RESPST_CHK_LENGTH : RESPST_ERR_RNR; + } + +@@ -938,12 +922,8 @@ static enum resp_states do_complete(struct rxe_qp *qp, + } + + /* have copy for srq and reference for !srq */ +- if (!qp->srq) { +- if (qp->is_user) +- advance_consumer(qp->rq.queue, QUEUE_TYPE_FROM_USER); +- else +- advance_consumer(qp->rq.queue, QUEUE_TYPE_KERNEL); +- } ++ if (!qp->srq) ++ queue_advance_consumer(qp->rq.queue, QUEUE_TYPE_FROM_CLIENT); + + qp->resp.wqe = NULL; + +@@ -1215,7 +1195,7 @@ static void rxe_drain_req_pkts(struct rxe_qp *qp, bool notify) + return; + + while (!qp->srq && q && queue_head(q, q->type)) +- advance_consumer(q, q->type); ++ queue_advance_consumer(q, q->type); + } + + int rxe_responder(void *arg) +diff --git a/drivers/infiniband/sw/rxe/rxe_srq.c b/drivers/infiniband/sw/rxe/rxe_srq.c +index 610c98d24b5cc..eb1c4c3b3a786 100644 +--- a/drivers/infiniband/sw/rxe/rxe_srq.c ++++ b/drivers/infiniband/sw/rxe/rxe_srq.c +@@ -86,14 +86,13 @@ int rxe_srq_from_init(struct rxe_dev *rxe, struct rxe_srq *srq, + srq->srq_num = srq->pelem.index; + srq->rq.max_wr = init->attr.max_wr; + srq->rq.max_sge = init->attr.max_sge; +- srq->rq.is_user = srq->is_user; + + srq_wqe_size = rcv_wqe_size(srq->rq.max_sge); + + spin_lock_init(&srq->rq.producer_lock); + spin_lock_init(&srq->rq.consumer_lock); + +- type = uresp ? QUEUE_TYPE_FROM_USER : QUEUE_TYPE_KERNEL; ++ type = QUEUE_TYPE_FROM_CLIENT; + q = rxe_queue_init(rxe, &srq->rq.max_wr, + srq_wqe_size, type); + if (!q) { +diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c +index 267b5a9c345d0..e40927cf5772e 100644 +--- a/drivers/infiniband/sw/rxe/rxe_verbs.c ++++ b/drivers/infiniband/sw/rxe/rxe_verbs.c +@@ -218,11 +218,7 @@ static int post_one_recv(struct rxe_rq *rq, const struct ib_recv_wr *ibwr) + int num_sge = ibwr->num_sge; + int full; + +- if (rq->is_user) +- full = queue_full(rq->queue, QUEUE_TYPE_FROM_USER); +- else +- full = queue_full(rq->queue, QUEUE_TYPE_KERNEL); +- ++ full = queue_full(rq->queue, QUEUE_TYPE_TO_DRIVER); + if (unlikely(full)) { + err = -ENOMEM; + goto err1; +@@ -237,11 +233,7 @@ static int post_one_recv(struct rxe_rq *rq, const struct ib_recv_wr *ibwr) + for (i = 0; i < num_sge; i++) + length += ibwr->sg_list[i].length; + +- if (rq->is_user) +- recv_wqe = producer_addr(rq->queue, QUEUE_TYPE_FROM_USER); +- else +- recv_wqe = producer_addr(rq->queue, QUEUE_TYPE_KERNEL); +- ++ recv_wqe = queue_producer_addr(rq->queue, QUEUE_TYPE_TO_DRIVER); + recv_wqe->wr_id = ibwr->wr_id; + recv_wqe->num_sge = num_sge; + +@@ -254,10 +246,7 @@ static int post_one_recv(struct rxe_rq *rq, const struct ib_recv_wr *ibwr) + recv_wqe->dma.cur_sge = 0; + recv_wqe->dma.sge_offset = 0; + +- if (rq->is_user) +- advance_producer(rq->queue, QUEUE_TYPE_FROM_USER); +- else +- advance_producer(rq->queue, QUEUE_TYPE_KERNEL); ++ queue_advance_producer(rq->queue, QUEUE_TYPE_TO_DRIVER); + + return 0; + +@@ -281,9 +270,6 @@ static int rxe_create_srq(struct ib_srq *ibsrq, struct ib_srq_init_attr *init, + if (udata->outlen < sizeof(*uresp)) + return -EINVAL; + uresp = udata->outbuf; +- srq->is_user = true; +- } else { +- srq->is_user = false; + } + + err = rxe_srq_chk_attr(rxe, NULL, &init->attr, IB_SRQ_INIT_MASK); +@@ -633,27 +619,17 @@ static int post_one_send(struct rxe_qp *qp, const struct ib_send_wr *ibwr, + + spin_lock_irqsave(&qp->sq.sq_lock, flags); + +- if (qp->is_user) +- full = queue_full(sq->queue, QUEUE_TYPE_FROM_USER); +- else +- full = queue_full(sq->queue, QUEUE_TYPE_KERNEL); ++ full = queue_full(sq->queue, QUEUE_TYPE_TO_DRIVER); + + if (unlikely(full)) { + spin_unlock_irqrestore(&qp->sq.sq_lock, flags); + return -ENOMEM; + } + +- if (qp->is_user) +- send_wqe = producer_addr(sq->queue, QUEUE_TYPE_FROM_USER); +- else +- send_wqe = producer_addr(sq->queue, QUEUE_TYPE_KERNEL); +- ++ send_wqe = queue_producer_addr(sq->queue, QUEUE_TYPE_TO_DRIVER); + init_send_wqe(qp, ibwr, mask, length, send_wqe); + +- if (qp->is_user) +- advance_producer(sq->queue, QUEUE_TYPE_FROM_USER); +- else +- advance_producer(sq->queue, QUEUE_TYPE_KERNEL); ++ queue_advance_producer(sq->queue, QUEUE_TYPE_TO_DRIVER); + + spin_unlock_irqrestore(&qp->sq.sq_lock, flags); + +@@ -845,18 +821,12 @@ static int rxe_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc) + + spin_lock_irqsave(&cq->cq_lock, flags); + for (i = 0; i < num_entries; i++) { +- if (cq->is_user) +- cqe = queue_head(cq->queue, QUEUE_TYPE_TO_USER); +- else +- cqe = queue_head(cq->queue, QUEUE_TYPE_KERNEL); ++ cqe = queue_head(cq->queue, QUEUE_TYPE_FROM_DRIVER); + if (!cqe) + break; + + memcpy(wc++, &cqe->ibwc, sizeof(*wc)); +- if (cq->is_user) +- advance_consumer(cq->queue, QUEUE_TYPE_TO_USER); +- else +- advance_consumer(cq->queue, QUEUE_TYPE_KERNEL); ++ queue_advance_consumer(cq->queue, QUEUE_TYPE_FROM_DRIVER); + } + spin_unlock_irqrestore(&cq->cq_lock, flags); + +@@ -868,10 +838,7 @@ static int rxe_peek_cq(struct ib_cq *ibcq, int wc_cnt) + struct rxe_cq *cq = to_rcq(ibcq); + int count; + +- if (cq->is_user) +- count = queue_count(cq->queue, QUEUE_TYPE_TO_USER); +- else +- count = queue_count(cq->queue, QUEUE_TYPE_KERNEL); ++ count = queue_count(cq->queue, QUEUE_TYPE_FROM_DRIVER); + + return (count > wc_cnt) ? wc_cnt : count; + } +@@ -887,10 +854,7 @@ static int rxe_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags) + if (cq->notify != IB_CQ_NEXT_COMP) + cq->notify = flags & IB_CQ_SOLICITED_MASK; + +- if (cq->is_user) +- empty = queue_empty(cq->queue, QUEUE_TYPE_TO_USER); +- else +- empty = queue_empty(cq->queue, QUEUE_TYPE_KERNEL); ++ empty = queue_empty(cq->queue, QUEUE_TYPE_FROM_DRIVER); + + if ((flags & IB_CQ_REPORT_MISSED_EVENTS) && !empty) + ret = 1; +diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h b/drivers/infiniband/sw/rxe/rxe_verbs.h +index d90b1d77de347..c852a9907bad4 100644 +--- a/drivers/infiniband/sw/rxe/rxe_verbs.h ++++ b/drivers/infiniband/sw/rxe/rxe_verbs.h +@@ -77,7 +77,6 @@ enum wqe_state { + }; + + struct rxe_sq { +- bool is_user; + int max_wr; + int max_sge; + int max_inline; +@@ -86,7 +85,6 @@ struct rxe_sq { + }; + + struct rxe_rq { +- bool is_user; + int max_wr; + int max_sge; + spinlock_t producer_lock; /* guard queue producer */ +@@ -100,7 +98,6 @@ struct rxe_srq { + struct rxe_pd *pd; + struct rxe_rq rq; + u32 srq_num; +- bool is_user; + + int limit; + int error; +diff --git a/drivers/infiniband/sw/siw/siw_cm.c b/drivers/infiniband/sw/siw/siw_cm.c +index 18a64ccbb0e58..69d639cab8985 100644 +--- a/drivers/infiniband/sw/siw/siw_cm.c ++++ b/drivers/infiniband/sw/siw/siw_cm.c +@@ -725,11 +725,11 @@ static int siw_proc_mpareply(struct siw_cep *cep) + enum mpa_v2_ctrl mpa_p2p_mode = MPA_V2_RDMA_NO_RTR; + + rv = siw_recv_mpa_rr(cep); +- if (rv != -EAGAIN) +- siw_cancel_mpatimer(cep); + if (rv) + goto out_err; + ++ siw_cancel_mpatimer(cep); ++ + rep = &cep->mpa.hdr; + + if (__mpa_rr_revision(rep->params.bits) > MPA_REVISION_2) { +@@ -895,7 +895,8 @@ static int siw_proc_mpareply(struct siw_cep *cep) + } + + out_err: +- siw_cm_upcall(cep, IW_CM_EVENT_CONNECT_REPLY, -EINVAL); ++ if (rv != -EAGAIN) ++ siw_cm_upcall(cep, IW_CM_EVENT_CONNECT_REPLY, -EINVAL); + + return rv; + } +diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c +index 776e46ee95dad..ef2d165d15a8b 100644 +--- a/drivers/infiniband/ulp/iser/iscsi_iser.c ++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c +@@ -584,7 +584,7 @@ iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session) + struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); + + iscsi_session_teardown(cls_session); +- iscsi_host_remove(shost); ++ iscsi_host_remove(shost, false); + iscsi_host_free(shost); + } + +@@ -702,7 +702,7 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep, + return cls_session; + + remove_host: +- iscsi_host_remove(shost); ++ iscsi_host_remove(shost, false); + free_host: + iscsi_host_free(shost); + return NULL; +diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt-stats.c b/drivers/infiniband/ulp/rtrs/rtrs-clt-stats.c +index 5e780bdd763d3..e7b57bdfe3ea0 100644 +--- a/drivers/infiniband/ulp/rtrs/rtrs-clt-stats.c ++++ b/drivers/infiniband/ulp/rtrs/rtrs-clt-stats.c +@@ -13,8 +13,8 @@ + + void rtrs_clt_update_wc_stats(struct rtrs_clt_con *con) + { +- struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); +- struct rtrs_clt_stats *stats = sess->stats; ++ struct rtrs_clt_path *clt_path = to_clt_path(con->c.path); ++ struct rtrs_clt_stats *stats = clt_path->stats; + struct rtrs_clt_stats_pcpu *s; + int cpu; + +@@ -174,8 +174,8 @@ static inline void rtrs_clt_update_rdma_stats(struct rtrs_clt_stats *stats, + void rtrs_clt_update_all_stats(struct rtrs_clt_io_req *req, int dir) + { + struct rtrs_clt_con *con = req->con; +- struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); +- struct rtrs_clt_stats *stats = sess->stats; ++ struct rtrs_clt_path *clt_path = to_clt_path(con->c.path); ++ struct rtrs_clt_stats *stats = clt_path->stats; + unsigned int len; + + len = req->usr_len + req->data_len; +diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c b/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c +index 4ee592ccf979b..dbf9a778c3bd7 100644 +--- a/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c ++++ b/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c +@@ -16,21 +16,21 @@ + #define MIN_MAX_RECONN_ATT -1 + #define MAX_MAX_RECONN_ATT 9999 + +-static void rtrs_clt_sess_release(struct kobject *kobj) ++static void rtrs_clt_path_release(struct kobject *kobj) + { +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + +- sess = container_of(kobj, struct rtrs_clt_sess, kobj); ++ clt_path = container_of(kobj, struct rtrs_clt_path, kobj); + +- free_sess(sess); ++ free_path(clt_path); + } + + static struct kobj_type ktype_sess = { + .sysfs_ops = &kobj_sysfs_ops, +- .release = rtrs_clt_sess_release ++ .release = rtrs_clt_path_release + }; + +-static void rtrs_clt_sess_stats_release(struct kobject *kobj) ++static void rtrs_clt_path_stats_release(struct kobject *kobj) + { + struct rtrs_clt_stats *stats; + +@@ -43,7 +43,7 @@ static void rtrs_clt_sess_stats_release(struct kobject *kobj) + + static struct kobj_type ktype_stats = { + .sysfs_ops = &kobj_sysfs_ops, +- .release = rtrs_clt_sess_stats_release, ++ .release = rtrs_clt_path_stats_release, + }; + + static ssize_t max_reconnect_attempts_show(struct device *dev, +@@ -197,10 +197,10 @@ static DEVICE_ATTR_RW(add_path); + static ssize_t rtrs_clt_state_show(struct kobject *kobj, + struct kobj_attribute *attr, char *page) + { +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + +- sess = container_of(kobj, struct rtrs_clt_sess, kobj); +- if (sess->state == RTRS_CLT_CONNECTED) ++ clt_path = container_of(kobj, struct rtrs_clt_path, kobj); ++ if (clt_path->state == RTRS_CLT_CONNECTED) + return sysfs_emit(page, "connected\n"); + + return sysfs_emit(page, "disconnected\n"); +@@ -219,16 +219,16 @@ static ssize_t rtrs_clt_reconnect_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) + { +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + int ret; + +- sess = container_of(kobj, struct rtrs_clt_sess, kobj); ++ clt_path = container_of(kobj, struct rtrs_clt_path, kobj); + if (!sysfs_streq(buf, "1")) { +- rtrs_err(sess->clt, "%s: unknown value: '%s'\n", ++ rtrs_err(clt_path->clt, "%s: unknown value: '%s'\n", + attr->attr.name, buf); + return -EINVAL; + } +- ret = rtrs_clt_reconnect_from_sysfs(sess); ++ ret = rtrs_clt_reconnect_from_sysfs(clt_path); + if (ret) + return ret; + +@@ -249,15 +249,15 @@ static ssize_t rtrs_clt_disconnect_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) + { +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + +- sess = container_of(kobj, struct rtrs_clt_sess, kobj); ++ clt_path = container_of(kobj, struct rtrs_clt_path, kobj); + if (!sysfs_streq(buf, "1")) { +- rtrs_err(sess->clt, "%s: unknown value: '%s'\n", ++ rtrs_err(clt_path->clt, "%s: unknown value: '%s'\n", + attr->attr.name, buf); + return -EINVAL; + } +- rtrs_clt_close_conns(sess, true); ++ rtrs_clt_close_conns(clt_path, true); + + return count; + } +@@ -276,16 +276,16 @@ static ssize_t rtrs_clt_remove_path_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) + { +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + int ret; + +- sess = container_of(kobj, struct rtrs_clt_sess, kobj); ++ clt_path = container_of(kobj, struct rtrs_clt_path, kobj); + if (!sysfs_streq(buf, "1")) { +- rtrs_err(sess->clt, "%s: unknown value: '%s'\n", ++ rtrs_err(clt_path->clt, "%s: unknown value: '%s'\n", + attr->attr.name, buf); + return -EINVAL; + } +- ret = rtrs_clt_remove_path_from_sysfs(sess, &attr->attr); ++ ret = rtrs_clt_remove_path_from_sysfs(clt_path, &attr->attr); + if (ret) + return ret; + +@@ -328,11 +328,11 @@ static ssize_t rtrs_clt_hca_port_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *page) + { +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + +- sess = container_of(kobj, typeof(*sess), kobj); ++ clt_path = container_of(kobj, typeof(*clt_path), kobj); + +- return sysfs_emit(page, "%u\n", sess->hca_port); ++ return sysfs_emit(page, "%u\n", clt_path->hca_port); + } + + static struct kobj_attribute rtrs_clt_hca_port_attr = +@@ -342,11 +342,11 @@ static ssize_t rtrs_clt_hca_name_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *page) + { +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + +- sess = container_of(kobj, struct rtrs_clt_sess, kobj); ++ clt_path = container_of(kobj, struct rtrs_clt_path, kobj); + +- return sysfs_emit(page, "%s\n", sess->hca_name); ++ return sysfs_emit(page, "%s\n", clt_path->hca_name); + } + + static struct kobj_attribute rtrs_clt_hca_name_attr = +@@ -356,12 +356,12 @@ static ssize_t rtrs_clt_cur_latency_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *page) + { +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + +- sess = container_of(kobj, struct rtrs_clt_sess, kobj); ++ clt_path = container_of(kobj, struct rtrs_clt_path, kobj); + + return sysfs_emit(page, "%lld ns\n", +- ktime_to_ns(sess->s.hb_cur_latency)); ++ ktime_to_ns(clt_path->s.hb_cur_latency)); + } + + static struct kobj_attribute rtrs_clt_cur_latency_attr = +@@ -371,11 +371,11 @@ static ssize_t rtrs_clt_src_addr_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *page) + { +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + int len; + +- sess = container_of(kobj, struct rtrs_clt_sess, kobj); +- len = sockaddr_to_str((struct sockaddr *)&sess->s.src_addr, page, ++ clt_path = container_of(kobj, struct rtrs_clt_path, kobj); ++ len = sockaddr_to_str((struct sockaddr *)&clt_path->s.src_addr, page, + PAGE_SIZE); + len += sysfs_emit_at(page, len, "\n"); + return len; +@@ -388,11 +388,11 @@ static ssize_t rtrs_clt_dst_addr_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *page) + { +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + int len; + +- sess = container_of(kobj, struct rtrs_clt_sess, kobj); +- len = sockaddr_to_str((struct sockaddr *)&sess->s.dst_addr, page, ++ clt_path = container_of(kobj, struct rtrs_clt_path, kobj); ++ len = sockaddr_to_str((struct sockaddr *)&clt_path->s.dst_addr, page, + PAGE_SIZE); + len += sysfs_emit_at(page, len, "\n"); + return len; +@@ -401,7 +401,7 @@ static ssize_t rtrs_clt_dst_addr_show(struct kobject *kobj, + static struct kobj_attribute rtrs_clt_dst_addr_attr = + __ATTR(dst_addr, 0444, rtrs_clt_dst_addr_show, NULL); + +-static struct attribute *rtrs_clt_sess_attrs[] = { ++static struct attribute *rtrs_clt_path_attrs[] = { + &rtrs_clt_hca_name_attr.attr, + &rtrs_clt_hca_port_attr.attr, + &rtrs_clt_src_addr_attr.attr, +@@ -414,42 +414,43 @@ static struct attribute *rtrs_clt_sess_attrs[] = { + NULL, + }; + +-static const struct attribute_group rtrs_clt_sess_attr_group = { +- .attrs = rtrs_clt_sess_attrs, ++static const struct attribute_group rtrs_clt_path_attr_group = { ++ .attrs = rtrs_clt_path_attrs, + }; + +-int rtrs_clt_create_sess_files(struct rtrs_clt_sess *sess) ++int rtrs_clt_create_path_files(struct rtrs_clt_path *clt_path) + { +- struct rtrs_clt *clt = sess->clt; ++ struct rtrs_clt *clt = clt_path->clt; + char str[NAME_MAX]; + int err; + struct rtrs_addr path = { +- .src = &sess->s.src_addr, +- .dst = &sess->s.dst_addr, ++ .src = &clt_path->s.src_addr, ++ .dst = &clt_path->s.dst_addr, + }; + + rtrs_addr_to_str(&path, str, sizeof(str)); +- err = kobject_init_and_add(&sess->kobj, &ktype_sess, clt->kobj_paths, ++ err = kobject_init_and_add(&clt_path->kobj, &ktype_sess, ++ clt->kobj_paths, + "%s", str); + if (err) { + pr_err("kobject_init_and_add: %d\n", err); +- kobject_put(&sess->kobj); ++ kobject_put(&clt_path->kobj); + return err; + } +- err = sysfs_create_group(&sess->kobj, &rtrs_clt_sess_attr_group); ++ err = sysfs_create_group(&clt_path->kobj, &rtrs_clt_path_attr_group); + if (err) { + pr_err("sysfs_create_group(): %d\n", err); + goto put_kobj; + } +- err = kobject_init_and_add(&sess->stats->kobj_stats, &ktype_stats, +- &sess->kobj, "stats"); ++ err = kobject_init_and_add(&clt_path->stats->kobj_stats, &ktype_stats, ++ &clt_path->kobj, "stats"); + if (err) { + pr_err("kobject_init_and_add: %d\n", err); +- kobject_put(&sess->stats->kobj_stats); ++ kobject_put(&clt_path->stats->kobj_stats); + goto remove_group; + } + +- err = sysfs_create_group(&sess->stats->kobj_stats, ++ err = sysfs_create_group(&clt_path->stats->kobj_stats, + &rtrs_clt_stats_attr_group); + if (err) { + pr_err("failed to create stats sysfs group, err: %d\n", err); +@@ -459,25 +460,25 @@ int rtrs_clt_create_sess_files(struct rtrs_clt_sess *sess) + return 0; + + put_kobj_stats: +- kobject_del(&sess->stats->kobj_stats); +- kobject_put(&sess->stats->kobj_stats); ++ kobject_del(&clt_path->stats->kobj_stats); ++ kobject_put(&clt_path->stats->kobj_stats); + remove_group: +- sysfs_remove_group(&sess->kobj, &rtrs_clt_sess_attr_group); ++ sysfs_remove_group(&clt_path->kobj, &rtrs_clt_path_attr_group); + put_kobj: +- kobject_del(&sess->kobj); +- kobject_put(&sess->kobj); ++ kobject_del(&clt_path->kobj); ++ kobject_put(&clt_path->kobj); + + return err; + } + +-void rtrs_clt_destroy_sess_files(struct rtrs_clt_sess *sess, ++void rtrs_clt_destroy_path_files(struct rtrs_clt_path *clt_path, + const struct attribute *sysfs_self) + { +- kobject_del(&sess->stats->kobj_stats); +- kobject_put(&sess->stats->kobj_stats); ++ kobject_del(&clt_path->stats->kobj_stats); ++ kobject_put(&clt_path->stats->kobj_stats); + if (sysfs_self) +- sysfs_remove_file_self(&sess->kobj, sysfs_self); +- kobject_del(&sess->kobj); ++ sysfs_remove_file_self(&clt_path->kobj, sysfs_self); ++ kobject_del(&clt_path->kobj); + } + + static struct attribute *rtrs_clt_attrs[] = { +diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c +index a23438bacf12c..9edbb309b96c0 100644 +--- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c ++++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c +@@ -48,12 +48,12 @@ static struct class *rtrs_clt_dev_class; + + static inline bool rtrs_clt_is_connected(const struct rtrs_clt *clt) + { +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + bool connected = false; + + rcu_read_lock(); +- list_for_each_entry_rcu(sess, &clt->paths_list, s.entry) +- connected |= READ_ONCE(sess->state) == RTRS_CLT_CONNECTED; ++ list_for_each_entry_rcu(clt_path, &clt->paths_list, s.entry) ++ connected |= READ_ONCE(clt_path->state) == RTRS_CLT_CONNECTED; + rcu_read_unlock(); + + return connected; +@@ -163,29 +163,29 @@ EXPORT_SYMBOL(rtrs_clt_put_permit); + + /** + * rtrs_permit_to_clt_con() - returns RDMA connection pointer by the permit +- * @sess: client session pointer ++ * @clt_path: client path pointer + * @permit: permit for the allocation of the RDMA buffer + * Note: + * IO connection starts from 1. + * 0 connection is for user messages. + */ + static +-struct rtrs_clt_con *rtrs_permit_to_clt_con(struct rtrs_clt_sess *sess, ++struct rtrs_clt_con *rtrs_permit_to_clt_con(struct rtrs_clt_path *clt_path, + struct rtrs_permit *permit) + { + int id = 0; + + if (permit->con_type == RTRS_IO_CON) +- id = (permit->cpu_id % (sess->s.irq_con_num - 1)) + 1; ++ id = (permit->cpu_id % (clt_path->s.irq_con_num - 1)) + 1; + +- return to_clt_con(sess->s.con[id]); ++ return to_clt_con(clt_path->s.con[id]); + } + + /** + * rtrs_clt_change_state() - change the session state through session state + * machine. + * +- * @sess: client session to change the state of. ++ * @clt_path: client path to change the state of. + * @new_state: state to change to. + * + * returns true if sess's state is changed to new state, otherwise return false. +@@ -193,15 +193,15 @@ struct rtrs_clt_con *rtrs_permit_to_clt_con(struct rtrs_clt_sess *sess, + * Locks: + * state_wq lock must be hold. + */ +-static bool rtrs_clt_change_state(struct rtrs_clt_sess *sess, ++static bool rtrs_clt_change_state(struct rtrs_clt_path *clt_path, + enum rtrs_clt_state new_state) + { + enum rtrs_clt_state old_state; + bool changed = false; + +- lockdep_assert_held(&sess->state_wq.lock); ++ lockdep_assert_held(&clt_path->state_wq.lock); + +- old_state = sess->state; ++ old_state = clt_path->state; + switch (new_state) { + case RTRS_CLT_CONNECTING: + switch (old_state) { +@@ -275,42 +275,42 @@ static bool rtrs_clt_change_state(struct rtrs_clt_sess *sess, + break; + } + if (changed) { +- sess->state = new_state; +- wake_up_locked(&sess->state_wq); ++ clt_path->state = new_state; ++ wake_up_locked(&clt_path->state_wq); + } + + return changed; + } + +-static bool rtrs_clt_change_state_from_to(struct rtrs_clt_sess *sess, ++static bool rtrs_clt_change_state_from_to(struct rtrs_clt_path *clt_path, + enum rtrs_clt_state old_state, + enum rtrs_clt_state new_state) + { + bool changed = false; + +- spin_lock_irq(&sess->state_wq.lock); +- if (sess->state == old_state) +- changed = rtrs_clt_change_state(sess, new_state); +- spin_unlock_irq(&sess->state_wq.lock); ++ spin_lock_irq(&clt_path->state_wq.lock); ++ if (clt_path->state == old_state) ++ changed = rtrs_clt_change_state(clt_path, new_state); ++ spin_unlock_irq(&clt_path->state_wq.lock); + + return changed; + } + + static void rtrs_rdma_error_recovery(struct rtrs_clt_con *con) + { +- struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); ++ struct rtrs_clt_path *clt_path = to_clt_path(con->c.path); + +- if (rtrs_clt_change_state_from_to(sess, ++ if (rtrs_clt_change_state_from_to(clt_path, + RTRS_CLT_CONNECTED, + RTRS_CLT_RECONNECTING)) { +- struct rtrs_clt *clt = sess->clt; ++ struct rtrs_clt *clt = clt_path->clt; + unsigned int delay_ms; + + /* + * Normal scenario, reconnect if we were successfully connected + */ + delay_ms = clt->reconnect_delay_sec * 1000; +- queue_delayed_work(rtrs_wq, &sess->reconnect_dwork, ++ queue_delayed_work(rtrs_wq, &clt_path->reconnect_dwork, + msecs_to_jiffies(delay_ms + + prandom_u32() % RTRS_RECONNECT_SEED)); + } else { +@@ -319,7 +319,7 @@ static void rtrs_rdma_error_recovery(struct rtrs_clt_con *con) + * so notify waiter with error state, waiter is responsible + * for cleaning the rest and reconnect if needed. + */ +- rtrs_clt_change_state_from_to(sess, ++ rtrs_clt_change_state_from_to(clt_path, + RTRS_CLT_CONNECTING, + RTRS_CLT_CONNECTING_ERR); + } +@@ -330,7 +330,7 @@ static void rtrs_clt_fast_reg_done(struct ib_cq *cq, struct ib_wc *wc) + struct rtrs_clt_con *con = to_clt_con(wc->qp->qp_context); + + if (wc->status != IB_WC_SUCCESS) { +- rtrs_err(con->c.sess, "Failed IB_WR_REG_MR: %s\n", ++ rtrs_err(con->c.path, "Failed IB_WR_REG_MR: %s\n", + ib_wc_status_msg(wc->status)); + rtrs_rdma_error_recovery(con); + } +@@ -350,7 +350,7 @@ static void rtrs_clt_inv_rkey_done(struct ib_cq *cq, struct ib_wc *wc) + struct rtrs_clt_con *con = to_clt_con(wc->qp->qp_context); + + if (wc->status != IB_WC_SUCCESS) { +- rtrs_err(con->c.sess, "Failed IB_WR_LOCAL_INV: %s\n", ++ rtrs_err(con->c.path, "Failed IB_WR_LOCAL_INV: %s\n", + ib_wc_status_msg(wc->status)); + rtrs_rdma_error_recovery(con); + } +@@ -380,14 +380,14 @@ static void complete_rdma_req(struct rtrs_clt_io_req *req, int errno, + bool notify, bool can_wait) + { + struct rtrs_clt_con *con = req->con; +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + int err; + + if (WARN_ON(!req->in_use)) + return; + if (WARN_ON(!req->con)) + return; +- sess = to_clt_sess(con->c.sess); ++ clt_path = to_clt_path(con->c.path); + + if (req->sg_cnt) { + if (req->dir == DMA_FROM_DEVICE && req->need_inv) { +@@ -417,7 +417,7 @@ static void complete_rdma_req(struct rtrs_clt_io_req *req, int errno, + refcount_inc(&req->ref); + err = rtrs_inv_rkey(req); + if (err) { +- rtrs_err(con->c.sess, "Send INV WR key=%#x: %d\n", ++ rtrs_err(con->c.path, "Send INV WR key=%#x: %d\n", + req->mr->rkey, err); + } else if (can_wait) { + wait_for_completion(&req->inv_comp); +@@ -433,21 +433,21 @@ static void complete_rdma_req(struct rtrs_clt_io_req *req, int errno, + if (!refcount_dec_and_test(&req->ref)) + return; + } +- ib_dma_unmap_sg(sess->s.dev->ib_dev, req->sglist, ++ ib_dma_unmap_sg(clt_path->s.dev->ib_dev, req->sglist, + req->sg_cnt, req->dir); + } + if (!refcount_dec_and_test(&req->ref)) + return; + if (req->mp_policy == MP_POLICY_MIN_INFLIGHT) +- atomic_dec(&sess->stats->inflight); ++ atomic_dec(&clt_path->stats->inflight); + + req->in_use = false; + req->con = NULL; + + if (errno) { +- rtrs_err_rl(con->c.sess, "IO request failed: error=%d path=%s [%s:%u] notify=%d\n", +- errno, kobject_name(&sess->kobj), sess->hca_name, +- sess->hca_port, notify); ++ rtrs_err_rl(con->c.path, "IO request failed: error=%d path=%s [%s:%u] notify=%d\n", ++ errno, kobject_name(&clt_path->kobj), clt_path->hca_name, ++ clt_path->hca_port, notify); + } + + if (notify) +@@ -459,12 +459,12 @@ static int rtrs_post_send_rdma(struct rtrs_clt_con *con, + struct rtrs_rbuf *rbuf, u32 off, + u32 imm, struct ib_send_wr *wr) + { +- struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); ++ struct rtrs_clt_path *clt_path = to_clt_path(con->c.path); + enum ib_send_flags flags; + struct ib_sge sge; + + if (!req->sg_size) { +- rtrs_wrn(con->c.sess, ++ rtrs_wrn(con->c.path, + "Doing RDMA Write failed, no data supplied\n"); + return -EINVAL; + } +@@ -472,16 +472,17 @@ static int rtrs_post_send_rdma(struct rtrs_clt_con *con, + /* user data and user message in the first list element */ + sge.addr = req->iu->dma_addr; + sge.length = req->sg_size; +- sge.lkey = sess->s.dev->ib_pd->local_dma_lkey; ++ sge.lkey = clt_path->s.dev->ib_pd->local_dma_lkey; + + /* + * From time to time we have to post signalled sends, + * or send queue will fill up and only QP reset can help. + */ +- flags = atomic_inc_return(&con->c.wr_cnt) % sess->s.signal_interval ? ++ flags = atomic_inc_return(&con->c.wr_cnt) % clt_path->s.signal_interval ? + 0 : IB_SEND_SIGNALED; + +- ib_dma_sync_single_for_device(sess->s.dev->ib_dev, req->iu->dma_addr, ++ ib_dma_sync_single_for_device(clt_path->s.dev->ib_dev, ++ req->iu->dma_addr, + req->sg_size, DMA_TO_DEVICE); + + return rtrs_iu_post_rdma_write_imm(&con->c, req->iu, &sge, 1, +@@ -489,15 +490,15 @@ static int rtrs_post_send_rdma(struct rtrs_clt_con *con, + imm, flags, wr, NULL); + } + +-static void process_io_rsp(struct rtrs_clt_sess *sess, u32 msg_id, ++static void process_io_rsp(struct rtrs_clt_path *clt_path, u32 msg_id, + s16 errno, bool w_inval) + { + struct rtrs_clt_io_req *req; + +- if (WARN_ON(msg_id >= sess->queue_depth)) ++ if (WARN_ON(msg_id >= clt_path->queue_depth)) + return; + +- req = &sess->reqs[msg_id]; ++ req = &clt_path->reqs[msg_id]; + /* Drop need_inv if server responded with send with invalidation */ + req->need_inv &= !w_inval; + complete_rdma_req(req, errno, true, false); +@@ -507,21 +508,21 @@ static void rtrs_clt_recv_done(struct rtrs_clt_con *con, struct ib_wc *wc) + { + struct rtrs_iu *iu; + int err; +- struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); ++ struct rtrs_clt_path *clt_path = to_clt_path(con->c.path); + +- WARN_ON((sess->flags & RTRS_MSG_NEW_RKEY_F) == 0); ++ WARN_ON((clt_path->flags & RTRS_MSG_NEW_RKEY_F) == 0); + iu = container_of(wc->wr_cqe, struct rtrs_iu, + cqe); + err = rtrs_iu_post_recv(&con->c, iu); + if (err) { +- rtrs_err(con->c.sess, "post iu failed %d\n", err); ++ rtrs_err(con->c.path, "post iu failed %d\n", err); + rtrs_rdma_error_recovery(con); + } + } + + static void rtrs_clt_rkey_rsp_done(struct rtrs_clt_con *con, struct ib_wc *wc) + { +- struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); ++ struct rtrs_clt_path *clt_path = to_clt_path(con->c.path); + struct rtrs_msg_rkey_rsp *msg; + u32 imm_type, imm_payload; + bool w_inval = false; +@@ -529,25 +530,26 @@ static void rtrs_clt_rkey_rsp_done(struct rtrs_clt_con *con, struct ib_wc *wc) + u32 buf_id; + int err; + +- WARN_ON((sess->flags & RTRS_MSG_NEW_RKEY_F) == 0); ++ WARN_ON((clt_path->flags & RTRS_MSG_NEW_RKEY_F) == 0); + + iu = container_of(wc->wr_cqe, struct rtrs_iu, cqe); + + if (wc->byte_len < sizeof(*msg)) { +- rtrs_err(con->c.sess, "rkey response is malformed: size %d\n", ++ rtrs_err(con->c.path, "rkey response is malformed: size %d\n", + wc->byte_len); + goto out; + } +- ib_dma_sync_single_for_cpu(sess->s.dev->ib_dev, iu->dma_addr, ++ ib_dma_sync_single_for_cpu(clt_path->s.dev->ib_dev, iu->dma_addr, + iu->size, DMA_FROM_DEVICE); + msg = iu->buf; + if (le16_to_cpu(msg->type) != RTRS_MSG_RKEY_RSP) { +- rtrs_err(sess->clt, "rkey response is malformed: type %d\n", ++ rtrs_err(clt_path->clt, ++ "rkey response is malformed: type %d\n", + le16_to_cpu(msg->type)); + goto out; + } + buf_id = le16_to_cpu(msg->buf_id); +- if (WARN_ON(buf_id >= sess->queue_depth)) ++ if (WARN_ON(buf_id >= clt_path->queue_depth)) + goto out; + + rtrs_from_imm(be32_to_cpu(wc->ex.imm_data), &imm_type, &imm_payload); +@@ -560,10 +562,10 @@ static void rtrs_clt_rkey_rsp_done(struct rtrs_clt_con *con, struct ib_wc *wc) + + if (WARN_ON(buf_id != msg_id)) + goto out; +- sess->rbufs[buf_id].rkey = le32_to_cpu(msg->rkey); +- process_io_rsp(sess, msg_id, err, w_inval); ++ clt_path->rbufs[buf_id].rkey = le32_to_cpu(msg->rkey); ++ process_io_rsp(clt_path, msg_id, err, w_inval); + } +- ib_dma_sync_single_for_device(sess->s.dev->ib_dev, iu->dma_addr, ++ ib_dma_sync_single_for_device(clt_path->s.dev->ib_dev, iu->dma_addr, + iu->size, DMA_FROM_DEVICE); + return rtrs_clt_recv_done(con, wc); + out: +@@ -600,14 +602,14 @@ static int rtrs_post_recv_empty_x2(struct rtrs_con *con, struct ib_cqe *cqe) + static void rtrs_clt_rdma_done(struct ib_cq *cq, struct ib_wc *wc) + { + struct rtrs_clt_con *con = to_clt_con(wc->qp->qp_context); +- struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); ++ struct rtrs_clt_path *clt_path = to_clt_path(con->c.path); + u32 imm_type, imm_payload; + bool w_inval = false; + int err; + + if (wc->status != IB_WC_SUCCESS) { + if (wc->status != IB_WC_WR_FLUSH_ERR) { +- rtrs_err(sess->clt, "RDMA failed: %s\n", ++ rtrs_err(clt_path->clt, "RDMA failed: %s\n", + ib_wc_status_msg(wc->status)); + rtrs_rdma_error_recovery(con); + } +@@ -632,21 +634,21 @@ static void rtrs_clt_rdma_done(struct ib_cq *cq, struct ib_wc *wc) + w_inval = (imm_type == RTRS_IO_RSP_W_INV_IMM); + rtrs_from_io_rsp_imm(imm_payload, &msg_id, &err); + +- process_io_rsp(sess, msg_id, err, w_inval); ++ process_io_rsp(clt_path, msg_id, err, w_inval); + } else if (imm_type == RTRS_HB_MSG_IMM) { + WARN_ON(con->c.cid); +- rtrs_send_hb_ack(&sess->s); +- if (sess->flags & RTRS_MSG_NEW_RKEY_F) ++ rtrs_send_hb_ack(&clt_path->s); ++ if (clt_path->flags & RTRS_MSG_NEW_RKEY_F) + return rtrs_clt_recv_done(con, wc); + } else if (imm_type == RTRS_HB_ACK_IMM) { + WARN_ON(con->c.cid); +- sess->s.hb_missed_cnt = 0; +- sess->s.hb_cur_latency = +- ktime_sub(ktime_get(), sess->s.hb_last_sent); +- if (sess->flags & RTRS_MSG_NEW_RKEY_F) ++ clt_path->s.hb_missed_cnt = 0; ++ clt_path->s.hb_cur_latency = ++ ktime_sub(ktime_get(), clt_path->s.hb_last_sent); ++ if (clt_path->flags & RTRS_MSG_NEW_RKEY_F) + return rtrs_clt_recv_done(con, wc); + } else { +- rtrs_wrn(con->c.sess, "Unknown IMM type %u\n", ++ rtrs_wrn(con->c.path, "Unknown IMM type %u\n", + imm_type); + } + if (w_inval) +@@ -658,7 +660,7 @@ static void rtrs_clt_rdma_done(struct ib_cq *cq, struct ib_wc *wc) + else + err = rtrs_post_recv_empty(&con->c, &io_comp_cqe); + if (err) { +- rtrs_err(con->c.sess, "rtrs_post_recv_empty(): %d\n", ++ rtrs_err(con->c.path, "rtrs_post_recv_empty(): %d\n", + err); + rtrs_rdma_error_recovery(con); + } +@@ -670,7 +672,7 @@ static void rtrs_clt_rdma_done(struct ib_cq *cq, struct ib_wc *wc) + WARN_ON(!(wc->wc_flags & IB_WC_WITH_INVALIDATE || + wc->wc_flags & IB_WC_WITH_IMM)); + WARN_ON(wc->wr_cqe->done != rtrs_clt_rdma_done); +- if (sess->flags & RTRS_MSG_NEW_RKEY_F) { ++ if (clt_path->flags & RTRS_MSG_NEW_RKEY_F) { + if (wc->wc_flags & IB_WC_WITH_INVALIDATE) + return rtrs_clt_recv_done(con, wc); + +@@ -685,7 +687,7 @@ static void rtrs_clt_rdma_done(struct ib_cq *cq, struct ib_wc *wc) + break; + + default: +- rtrs_wrn(sess->clt, "Unexpected WC type: %d\n", wc->opcode); ++ rtrs_wrn(clt_path->clt, "Unexpected WC type: %d\n", wc->opcode); + return; + } + } +@@ -693,10 +695,10 @@ static void rtrs_clt_rdma_done(struct ib_cq *cq, struct ib_wc *wc) + static int post_recv_io(struct rtrs_clt_con *con, size_t q_size) + { + int err, i; +- struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); ++ struct rtrs_clt_path *clt_path = to_clt_path(con->c.path); + + for (i = 0; i < q_size; i++) { +- if (sess->flags & RTRS_MSG_NEW_RKEY_F) { ++ if (clt_path->flags & RTRS_MSG_NEW_RKEY_F) { + struct rtrs_iu *iu = &con->rsp_ius[i]; + + err = rtrs_iu_post_recv(&con->c, iu); +@@ -710,16 +712,16 @@ static int post_recv_io(struct rtrs_clt_con *con, size_t q_size) + return 0; + } + +-static int post_recv_sess(struct rtrs_clt_sess *sess) ++static int post_recv_path(struct rtrs_clt_path *clt_path) + { + size_t q_size = 0; + int err, cid; + +- for (cid = 0; cid < sess->s.con_num; cid++) { ++ for (cid = 0; cid < clt_path->s.con_num; cid++) { + if (cid == 0) + q_size = SERVICE_CON_QUEUE_DEPTH; + else +- q_size = sess->queue_depth; ++ q_size = clt_path->queue_depth; + + /* + * x2 for RDMA read responses + FR key invalidations, +@@ -727,9 +729,10 @@ static int post_recv_sess(struct rtrs_clt_sess *sess) + */ + q_size *= 2; + +- err = post_recv_io(to_clt_con(sess->s.con[cid]), q_size); ++ err = post_recv_io(to_clt_con(clt_path->s.con[cid]), q_size); + if (err) { +- rtrs_err(sess->clt, "post_recv_io(), err: %d\n", err); ++ rtrs_err(clt_path->clt, "post_recv_io(), err: %d\n", ++ err); + return err; + } + } +@@ -741,28 +744,28 @@ struct path_it { + int i; + struct list_head skip_list; + struct rtrs_clt *clt; +- struct rtrs_clt_sess *(*next_path)(struct path_it *it); ++ struct rtrs_clt_path *(*next_path)(struct path_it *it); + }; + +-/** +- * list_next_or_null_rr_rcu - get next list element in round-robin fashion. ++/* ++ * rtrs_clt_get_next_path_or_null - get clt path from the list or return NULL + * @head: the head for the list. +- * @ptr: the list head to take the next element from. +- * @type: the type of the struct this is embedded in. +- * @memb: the name of the list_head within the struct. ++ * @clt_path: The element to take the next clt_path from. + * +- * Next element returned in round-robin fashion, i.e. head will be skipped, ++ * Next clt path returned in round-robin fashion, i.e. head will be skipped, + * but if list is observed as empty, NULL will be returned. + * +- * This primitive may safely run concurrently with the _rcu list-mutation ++ * This function may safely run concurrently with the _rcu list-mutation + * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock(). + */ +-#define list_next_or_null_rr_rcu(head, ptr, type, memb) \ +-({ \ +- list_next_or_null_rcu(head, ptr, type, memb) ?: \ +- list_next_or_null_rcu(head, READ_ONCE((ptr)->next), \ +- type, memb); \ +-}) ++static inline struct rtrs_clt_path * ++rtrs_clt_get_next_path_or_null(struct list_head *head, struct rtrs_clt_path *clt_path) ++{ ++ return list_next_or_null_rcu(head, &clt_path->s.entry, typeof(*clt_path), s.entry) ?: ++ list_next_or_null_rcu(head, ++ READ_ONCE((&clt_path->s.entry)->next), ++ typeof(*clt_path), s.entry); ++} + + /** + * get_next_path_rr() - Returns path in round-robin fashion. +@@ -773,10 +776,10 @@ struct path_it { + * Locks: + * rcu_read_lock() must be hold. + */ +-static struct rtrs_clt_sess *get_next_path_rr(struct path_it *it) ++static struct rtrs_clt_path *get_next_path_rr(struct path_it *it) + { +- struct rtrs_clt_sess __rcu **ppcpu_path; +- struct rtrs_clt_sess *path; ++ struct rtrs_clt_path __rcu **ppcpu_path; ++ struct rtrs_clt_path *path; + struct rtrs_clt *clt; + + clt = it->clt; +@@ -793,10 +796,8 @@ static struct rtrs_clt_sess *get_next_path_rr(struct path_it *it) + path = list_first_or_null_rcu(&clt->paths_list, + typeof(*path), s.entry); + else +- path = list_next_or_null_rr_rcu(&clt->paths_list, +- &path->s.entry, +- typeof(*path), +- s.entry); ++ path = rtrs_clt_get_next_path_or_null(&clt->paths_list, path); ++ + rcu_assign_pointer(*ppcpu_path, path); + + return path; +@@ -811,26 +812,26 @@ static struct rtrs_clt_sess *get_next_path_rr(struct path_it *it) + * Locks: + * rcu_read_lock() must be hold. + */ +-static struct rtrs_clt_sess *get_next_path_min_inflight(struct path_it *it) ++static struct rtrs_clt_path *get_next_path_min_inflight(struct path_it *it) + { +- struct rtrs_clt_sess *min_path = NULL; ++ struct rtrs_clt_path *min_path = NULL; + struct rtrs_clt *clt = it->clt; +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + int min_inflight = INT_MAX; + int inflight; + +- list_for_each_entry_rcu(sess, &clt->paths_list, s.entry) { +- if (READ_ONCE(sess->state) != RTRS_CLT_CONNECTED) ++ list_for_each_entry_rcu(clt_path, &clt->paths_list, s.entry) { ++ if (READ_ONCE(clt_path->state) != RTRS_CLT_CONNECTED) + continue; + +- if (!list_empty(raw_cpu_ptr(sess->mp_skip_entry))) ++ if (!list_empty(raw_cpu_ptr(clt_path->mp_skip_entry))) + continue; + +- inflight = atomic_read(&sess->stats->inflight); ++ inflight = atomic_read(&clt_path->stats->inflight); + + if (inflight < min_inflight) { + min_inflight = inflight; +- min_path = sess; ++ min_path = clt_path; + } + } + +@@ -862,26 +863,26 @@ static struct rtrs_clt_sess *get_next_path_min_inflight(struct path_it *it) + * Therefore the caller MUST check the returned + * path is NULL and trigger the IO error. + */ +-static struct rtrs_clt_sess *get_next_path_min_latency(struct path_it *it) ++static struct rtrs_clt_path *get_next_path_min_latency(struct path_it *it) + { +- struct rtrs_clt_sess *min_path = NULL; ++ struct rtrs_clt_path *min_path = NULL; + struct rtrs_clt *clt = it->clt; +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + ktime_t min_latency = KTIME_MAX; + ktime_t latency; + +- list_for_each_entry_rcu(sess, &clt->paths_list, s.entry) { +- if (READ_ONCE(sess->state) != RTRS_CLT_CONNECTED) ++ list_for_each_entry_rcu(clt_path, &clt->paths_list, s.entry) { ++ if (READ_ONCE(clt_path->state) != RTRS_CLT_CONNECTED) + continue; + +- if (!list_empty(raw_cpu_ptr(sess->mp_skip_entry))) ++ if (!list_empty(raw_cpu_ptr(clt_path->mp_skip_entry))) + continue; + +- latency = sess->s.hb_cur_latency; ++ latency = clt_path->s.hb_cur_latency; + + if (latency < min_latency) { + min_latency = latency; +- min_path = sess; ++ min_path = clt_path; + } + } + +@@ -928,7 +929,7 @@ static inline void path_it_deinit(struct path_it *it) + * the corresponding buffer of rtrs_iu (req->iu->buf), which later on will + * also hold the control message of rtrs. + * @req: an io request holding information about IO. +- * @sess: client session ++ * @clt_path: client path + * @conf: conformation callback function to notify upper layer. + * @permit: permit for allocation of RDMA remote buffer + * @priv: private pointer +@@ -940,7 +941,7 @@ static inline void path_it_deinit(struct path_it *it) + * @dir: direction of the IO. + */ + static void rtrs_clt_init_req(struct rtrs_clt_io_req *req, +- struct rtrs_clt_sess *sess, ++ struct rtrs_clt_path *clt_path, + void (*conf)(void *priv, int errno), + struct rtrs_permit *permit, void *priv, + const struct kvec *vec, size_t usr_len, +@@ -958,13 +959,13 @@ static void rtrs_clt_init_req(struct rtrs_clt_io_req *req, + req->sg_cnt = sg_cnt; + req->priv = priv; + req->dir = dir; +- req->con = rtrs_permit_to_clt_con(sess, permit); ++ req->con = rtrs_permit_to_clt_con(clt_path, permit); + req->conf = conf; + req->need_inv = false; + req->need_inv_comp = false; + req->inv_errno = 0; + refcount_set(&req->ref, 1); +- req->mp_policy = sess->clt->mp_policy; ++ req->mp_policy = clt_path->clt->mp_policy; + + iov_iter_kvec(&iter, READ, vec, 1, usr_len); + len = _copy_from_iter(req->iu->buf, usr_len, &iter); +@@ -974,7 +975,7 @@ static void rtrs_clt_init_req(struct rtrs_clt_io_req *req, + } + + static struct rtrs_clt_io_req * +-rtrs_clt_get_req(struct rtrs_clt_sess *sess, ++rtrs_clt_get_req(struct rtrs_clt_path *clt_path, + void (*conf)(void *priv, int errno), + struct rtrs_permit *permit, void *priv, + const struct kvec *vec, size_t usr_len, +@@ -983,14 +984,14 @@ rtrs_clt_get_req(struct rtrs_clt_sess *sess, + { + struct rtrs_clt_io_req *req; + +- req = &sess->reqs[permit->mem_id]; +- rtrs_clt_init_req(req, sess, conf, permit, priv, vec, usr_len, ++ req = &clt_path->reqs[permit->mem_id]; ++ rtrs_clt_init_req(req, clt_path, conf, permit, priv, vec, usr_len, + sg, sg_cnt, data_len, dir); + return req; + } + + static struct rtrs_clt_io_req * +-rtrs_clt_get_copy_req(struct rtrs_clt_sess *alive_sess, ++rtrs_clt_get_copy_req(struct rtrs_clt_path *alive_path, + struct rtrs_clt_io_req *fail_req) + { + struct rtrs_clt_io_req *req; +@@ -999,8 +1000,8 @@ rtrs_clt_get_copy_req(struct rtrs_clt_sess *alive_sess, + .iov_len = fail_req->usr_len + }; + +- req = &alive_sess->reqs[fail_req->permit->mem_id]; +- rtrs_clt_init_req(req, alive_sess, fail_req->conf, fail_req->permit, ++ req = &alive_path->reqs[fail_req->permit->mem_id]; ++ rtrs_clt_init_req(req, alive_path, fail_req->conf, fail_req->permit, + fail_req->priv, &vec, fail_req->usr_len, + fail_req->sglist, fail_req->sg_cnt, + fail_req->data_len, fail_req->dir); +@@ -1013,7 +1014,7 @@ static int rtrs_post_rdma_write_sg(struct rtrs_clt_con *con, + u32 size, u32 imm, struct ib_send_wr *wr, + struct ib_send_wr *tail) + { +- struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); ++ struct rtrs_clt_path *clt_path = to_clt_path(con->c.path); + struct ib_sge *sge = req->sge; + enum ib_send_flags flags; + struct scatterlist *sg; +@@ -1033,22 +1034,23 @@ static int rtrs_post_rdma_write_sg(struct rtrs_clt_con *con, + for_each_sg(req->sglist, sg, req->sg_cnt, i) { + sge[i].addr = sg_dma_address(sg); + sge[i].length = sg_dma_len(sg); +- sge[i].lkey = sess->s.dev->ib_pd->local_dma_lkey; ++ sge[i].lkey = clt_path->s.dev->ib_pd->local_dma_lkey; + } + num_sge = 1 + req->sg_cnt; + } + sge[i].addr = req->iu->dma_addr; + sge[i].length = size; +- sge[i].lkey = sess->s.dev->ib_pd->local_dma_lkey; ++ sge[i].lkey = clt_path->s.dev->ib_pd->local_dma_lkey; + + /* + * From time to time we have to post signalled sends, + * or send queue will fill up and only QP reset can help. + */ +- flags = atomic_inc_return(&con->c.wr_cnt) % sess->s.signal_interval ? ++ flags = atomic_inc_return(&con->c.wr_cnt) % clt_path->s.signal_interval ? + 0 : IB_SEND_SIGNALED; + +- ib_dma_sync_single_for_device(sess->s.dev->ib_dev, req->iu->dma_addr, ++ ib_dma_sync_single_for_device(clt_path->s.dev->ib_dev, ++ req->iu->dma_addr, + size, DMA_TO_DEVICE); + + return rtrs_iu_post_rdma_write_imm(&con->c, req->iu, sge, num_sge, +@@ -1074,8 +1076,8 @@ static int rtrs_map_sg_fr(struct rtrs_clt_io_req *req, size_t count) + static int rtrs_clt_write_req(struct rtrs_clt_io_req *req) + { + struct rtrs_clt_con *con = req->con; +- struct rtrs_sess *s = con->c.sess; +- struct rtrs_clt_sess *sess = to_clt_sess(s); ++ struct rtrs_path *s = con->c.path; ++ struct rtrs_clt_path *clt_path = to_clt_path(s); + struct rtrs_msg_rdma_write *msg; + + struct rtrs_rbuf *rbuf; +@@ -1088,13 +1090,13 @@ static int rtrs_clt_write_req(struct rtrs_clt_io_req *req) + + const size_t tsize = sizeof(*msg) + req->data_len + req->usr_len; + +- if (tsize > sess->chunk_size) { ++ if (tsize > clt_path->chunk_size) { + rtrs_wrn(s, "Write request failed, size too big %zu > %d\n", +- tsize, sess->chunk_size); ++ tsize, clt_path->chunk_size); + return -EMSGSIZE; + } + if (req->sg_cnt) { +- count = ib_dma_map_sg(sess->s.dev->ib_dev, req->sglist, ++ count = ib_dma_map_sg(clt_path->s.dev->ib_dev, req->sglist, + req->sg_cnt, req->dir); + if (!count) { + rtrs_wrn(s, "Write request failed, map failed\n"); +@@ -1111,7 +1113,7 @@ static int rtrs_clt_write_req(struct rtrs_clt_io_req *req) + imm = rtrs_to_io_req_imm(imm); + buf_id = req->permit->mem_id; + req->sg_size = tsize; +- rbuf = &sess->rbufs[buf_id]; ++ rbuf = &clt_path->rbufs[buf_id]; + + if (count) { + ret = rtrs_map_sg_fr(req, count); +@@ -1119,7 +1121,7 @@ static int rtrs_clt_write_req(struct rtrs_clt_io_req *req) + rtrs_err_rl(s, + "Write request failed, failed to map fast reg. data, err: %d\n", + ret); +- ib_dma_unmap_sg(sess->s.dev->ib_dev, req->sglist, ++ ib_dma_unmap_sg(clt_path->s.dev->ib_dev, req->sglist, + req->sg_cnt, req->dir); + return ret; + } +@@ -1153,12 +1155,12 @@ static int rtrs_clt_write_req(struct rtrs_clt_io_req *req) + if (ret) { + rtrs_err_rl(s, + "Write request failed: error=%d path=%s [%s:%u]\n", +- ret, kobject_name(&sess->kobj), sess->hca_name, +- sess->hca_port); ++ ret, kobject_name(&clt_path->kobj), clt_path->hca_name, ++ clt_path->hca_port); + if (req->mp_policy == MP_POLICY_MIN_INFLIGHT) +- atomic_dec(&sess->stats->inflight); ++ atomic_dec(&clt_path->stats->inflight); + if (req->sg_cnt) +- ib_dma_unmap_sg(sess->s.dev->ib_dev, req->sglist, ++ ib_dma_unmap_sg(clt_path->s.dev->ib_dev, req->sglist, + req->sg_cnt, req->dir); + } + +@@ -1168,10 +1170,10 @@ static int rtrs_clt_write_req(struct rtrs_clt_io_req *req) + static int rtrs_clt_read_req(struct rtrs_clt_io_req *req) + { + struct rtrs_clt_con *con = req->con; +- struct rtrs_sess *s = con->c.sess; +- struct rtrs_clt_sess *sess = to_clt_sess(s); ++ struct rtrs_path *s = con->c.path; ++ struct rtrs_clt_path *clt_path = to_clt_path(s); + struct rtrs_msg_rdma_read *msg; +- struct rtrs_ib_dev *dev = sess->s.dev; ++ struct rtrs_ib_dev *dev = clt_path->s.dev; + + struct ib_reg_wr rwr; + struct ib_send_wr *wr = NULL; +@@ -1181,10 +1183,10 @@ static int rtrs_clt_read_req(struct rtrs_clt_io_req *req) + + const size_t tsize = sizeof(*msg) + req->data_len + req->usr_len; + +- if (tsize > sess->chunk_size) { ++ if (tsize > clt_path->chunk_size) { + rtrs_wrn(s, + "Read request failed, message size is %zu, bigger than CHUNK_SIZE %d\n", +- tsize, sess->chunk_size); ++ tsize, clt_path->chunk_size); + return -EMSGSIZE; + } + +@@ -1254,15 +1256,15 @@ static int rtrs_clt_read_req(struct rtrs_clt_io_req *req) + */ + rtrs_clt_update_all_stats(req, READ); + +- ret = rtrs_post_send_rdma(req->con, req, &sess->rbufs[buf_id], ++ ret = rtrs_post_send_rdma(req->con, req, &clt_path->rbufs[buf_id], + req->data_len, imm, wr); + if (ret) { + rtrs_err_rl(s, + "Read request failed: error=%d path=%s [%s:%u]\n", +- ret, kobject_name(&sess->kobj), sess->hca_name, +- sess->hca_port); ++ ret, kobject_name(&clt_path->kobj), clt_path->hca_name, ++ clt_path->hca_port); + if (req->mp_policy == MP_POLICY_MIN_INFLIGHT) +- atomic_dec(&sess->stats->inflight); ++ atomic_dec(&clt_path->stats->inflight); + req->need_inv = false; + if (req->sg_cnt) + ib_dma_unmap_sg(dev->ib_dev, req->sglist, +@@ -1280,18 +1282,18 @@ static int rtrs_clt_read_req(struct rtrs_clt_io_req *req) + static int rtrs_clt_failover_req(struct rtrs_clt *clt, + struct rtrs_clt_io_req *fail_req) + { +- struct rtrs_clt_sess *alive_sess; ++ struct rtrs_clt_path *alive_path; + struct rtrs_clt_io_req *req; + int err = -ECONNABORTED; + struct path_it it; + + rcu_read_lock(); + for (path_it_init(&it, clt); +- (alive_sess = it.next_path(&it)) && it.i < it.clt->paths_num; ++ (alive_path = it.next_path(&it)) && it.i < it.clt->paths_num; + it.i++) { +- if (READ_ONCE(alive_sess->state) != RTRS_CLT_CONNECTED) ++ if (READ_ONCE(alive_path->state) != RTRS_CLT_CONNECTED) + continue; +- req = rtrs_clt_get_copy_req(alive_sess, fail_req); ++ req = rtrs_clt_get_copy_req(alive_path, fail_req); + if (req->dir == DMA_TO_DEVICE) + err = rtrs_clt_write_req(req); + else +@@ -1301,7 +1303,7 @@ static int rtrs_clt_failover_req(struct rtrs_clt *clt, + continue; + } + /* Success path */ +- rtrs_clt_inc_failover_cnt(alive_sess->stats); ++ rtrs_clt_inc_failover_cnt(alive_path->stats); + break; + } + path_it_deinit(&it); +@@ -1310,16 +1312,16 @@ static int rtrs_clt_failover_req(struct rtrs_clt *clt, + return err; + } + +-static void fail_all_outstanding_reqs(struct rtrs_clt_sess *sess) ++static void fail_all_outstanding_reqs(struct rtrs_clt_path *clt_path) + { +- struct rtrs_clt *clt = sess->clt; ++ struct rtrs_clt *clt = clt_path->clt; + struct rtrs_clt_io_req *req; + int i, err; + +- if (!sess->reqs) ++ if (!clt_path->reqs) + return; +- for (i = 0; i < sess->queue_depth; ++i) { +- req = &sess->reqs[i]; ++ for (i = 0; i < clt_path->queue_depth; ++i) { ++ req = &clt_path->reqs[i]; + if (!req->in_use) + continue; + +@@ -1337,38 +1339,39 @@ static void fail_all_outstanding_reqs(struct rtrs_clt_sess *sess) + } + } + +-static void free_sess_reqs(struct rtrs_clt_sess *sess) ++static void free_path_reqs(struct rtrs_clt_path *clt_path) + { + struct rtrs_clt_io_req *req; + int i; + +- if (!sess->reqs) ++ if (!clt_path->reqs) + return; +- for (i = 0; i < sess->queue_depth; ++i) { +- req = &sess->reqs[i]; ++ for (i = 0; i < clt_path->queue_depth; ++i) { ++ req = &clt_path->reqs[i]; + if (req->mr) + ib_dereg_mr(req->mr); + kfree(req->sge); +- rtrs_iu_free(req->iu, sess->s.dev->ib_dev, 1); ++ rtrs_iu_free(req->iu, clt_path->s.dev->ib_dev, 1); + } +- kfree(sess->reqs); +- sess->reqs = NULL; ++ kfree(clt_path->reqs); ++ clt_path->reqs = NULL; + } + +-static int alloc_sess_reqs(struct rtrs_clt_sess *sess) ++static int alloc_path_reqs(struct rtrs_clt_path *clt_path) + { + struct rtrs_clt_io_req *req; + int i, err = -ENOMEM; + +- sess->reqs = kcalloc(sess->queue_depth, sizeof(*sess->reqs), +- GFP_KERNEL); +- if (!sess->reqs) ++ clt_path->reqs = kcalloc(clt_path->queue_depth, ++ sizeof(*clt_path->reqs), ++ GFP_KERNEL); ++ if (!clt_path->reqs) + return -ENOMEM; + +- for (i = 0; i < sess->queue_depth; ++i) { +- req = &sess->reqs[i]; +- req->iu = rtrs_iu_alloc(1, sess->max_hdr_size, GFP_KERNEL, +- sess->s.dev->ib_dev, ++ for (i = 0; i < clt_path->queue_depth; ++i) { ++ req = &clt_path->reqs[i]; ++ req->iu = rtrs_iu_alloc(1, clt_path->max_hdr_size, GFP_KERNEL, ++ clt_path->s.dev->ib_dev, + DMA_TO_DEVICE, + rtrs_clt_rdma_done); + if (!req->iu) +@@ -1378,13 +1381,14 @@ static int alloc_sess_reqs(struct rtrs_clt_sess *sess) + if (!req->sge) + goto out; + +- req->mr = ib_alloc_mr(sess->s.dev->ib_pd, IB_MR_TYPE_MEM_REG, +- sess->max_pages_per_mr); ++ req->mr = ib_alloc_mr(clt_path->s.dev->ib_pd, ++ IB_MR_TYPE_MEM_REG, ++ clt_path->max_pages_per_mr); + if (IS_ERR(req->mr)) { + err = PTR_ERR(req->mr); + req->mr = NULL; +- pr_err("Failed to alloc sess->max_pages_per_mr %d\n", +- sess->max_pages_per_mr); ++ pr_err("Failed to alloc clt_path->max_pages_per_mr %d\n", ++ clt_path->max_pages_per_mr); + goto out; + } + +@@ -1394,7 +1398,7 @@ static int alloc_sess_reqs(struct rtrs_clt_sess *sess) + return 0; + + out: +- free_sess_reqs(sess); ++ free_path_reqs(clt_path); + + return err; + } +@@ -1447,13 +1451,13 @@ static void free_permits(struct rtrs_clt *clt) + clt->permits = NULL; + } + +-static void query_fast_reg_mode(struct rtrs_clt_sess *sess) ++static void query_fast_reg_mode(struct rtrs_clt_path *clt_path) + { + struct ib_device *ib_dev; + u64 max_pages_per_mr; + int mr_page_shift; + +- ib_dev = sess->s.dev->ib_dev; ++ ib_dev = clt_path->s.dev->ib_dev; + + /* + * Use the smallest page size supported by the HCA, down to a +@@ -1463,24 +1467,24 @@ static void query_fast_reg_mode(struct rtrs_clt_sess *sess) + mr_page_shift = max(12, ffs(ib_dev->attrs.page_size_cap) - 1); + max_pages_per_mr = ib_dev->attrs.max_mr_size; + do_div(max_pages_per_mr, (1ull << mr_page_shift)); +- sess->max_pages_per_mr = +- min3(sess->max_pages_per_mr, (u32)max_pages_per_mr, ++ clt_path->max_pages_per_mr = ++ min3(clt_path->max_pages_per_mr, (u32)max_pages_per_mr, + ib_dev->attrs.max_fast_reg_page_list_len); +- sess->clt->max_segments = +- min(sess->max_pages_per_mr, sess->clt->max_segments); ++ clt_path->clt->max_segments = ++ min(clt_path->max_pages_per_mr, clt_path->clt->max_segments); + } + +-static bool rtrs_clt_change_state_get_old(struct rtrs_clt_sess *sess, ++static bool rtrs_clt_change_state_get_old(struct rtrs_clt_path *clt_path, + enum rtrs_clt_state new_state, + enum rtrs_clt_state *old_state) + { + bool changed; + +- spin_lock_irq(&sess->state_wq.lock); ++ spin_lock_irq(&clt_path->state_wq.lock); + if (old_state) +- *old_state = sess->state; +- changed = rtrs_clt_change_state(sess, new_state); +- spin_unlock_irq(&sess->state_wq.lock); ++ *old_state = clt_path->state; ++ changed = rtrs_clt_change_state(clt_path, new_state); ++ spin_unlock_irq(&clt_path->state_wq.lock); + + return changed; + } +@@ -1492,9 +1496,9 @@ static void rtrs_clt_hb_err_handler(struct rtrs_con *c) + rtrs_rdma_error_recovery(con); + } + +-static void rtrs_clt_init_hb(struct rtrs_clt_sess *sess) ++static void rtrs_clt_init_hb(struct rtrs_clt_path *clt_path) + { +- rtrs_init_hb(&sess->s, &io_comp_cqe, ++ rtrs_init_hb(&clt_path->s, &io_comp_cqe, + RTRS_HB_INTERVAL_MS, + RTRS_HB_MISSED_MAX, + rtrs_clt_hb_err_handler, +@@ -1504,17 +1508,17 @@ static void rtrs_clt_init_hb(struct rtrs_clt_sess *sess) + static void rtrs_clt_reconnect_work(struct work_struct *work); + static void rtrs_clt_close_work(struct work_struct *work); + +-static struct rtrs_clt_sess *alloc_sess(struct rtrs_clt *clt, ++static struct rtrs_clt_path *alloc_path(struct rtrs_clt *clt, + const struct rtrs_addr *path, + size_t con_num, u32 nr_poll_queues) + { +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + int err = -ENOMEM; + int cpu; + size_t total_con; + +- sess = kzalloc(sizeof(*sess), GFP_KERNEL); +- if (!sess) ++ clt_path = kzalloc(sizeof(*clt_path), GFP_KERNEL); ++ if (!clt_path) + goto err; + + /* +@@ -1522,20 +1526,21 @@ static struct rtrs_clt_sess *alloc_sess(struct rtrs_clt *clt, + * +1: Extra connection for user messages + */ + total_con = con_num + nr_poll_queues + 1; +- sess->s.con = kcalloc(total_con, sizeof(*sess->s.con), GFP_KERNEL); +- if (!sess->s.con) +- goto err_free_sess; ++ clt_path->s.con = kcalloc(total_con, sizeof(*clt_path->s.con), ++ GFP_KERNEL); ++ if (!clt_path->s.con) ++ goto err_free_path; + +- sess->s.con_num = total_con; +- sess->s.irq_con_num = con_num + 1; ++ clt_path->s.con_num = total_con; ++ clt_path->s.irq_con_num = con_num + 1; + +- sess->stats = kzalloc(sizeof(*sess->stats), GFP_KERNEL); +- if (!sess->stats) ++ clt_path->stats = kzalloc(sizeof(*clt_path->stats), GFP_KERNEL); ++ if (!clt_path->stats) + goto err_free_con; + +- mutex_init(&sess->init_mutex); +- uuid_gen(&sess->s.uuid); +- memcpy(&sess->s.dst_addr, path->dst, ++ mutex_init(&clt_path->init_mutex); ++ uuid_gen(&clt_path->s.uuid); ++ memcpy(&clt_path->s.dst_addr, path->dst, + rdma_addr_size((struct sockaddr *)path->dst)); + + /* +@@ -1544,53 +1549,54 @@ static struct rtrs_clt_sess *alloc_sess(struct rtrs_clt *clt, + * the sess->src_addr will contain only zeros, which is then fine. + */ + if (path->src) +- memcpy(&sess->s.src_addr, path->src, ++ memcpy(&clt_path->s.src_addr, path->src, + rdma_addr_size((struct sockaddr *)path->src)); +- strscpy(sess->s.sessname, clt->sessname, sizeof(sess->s.sessname)); +- sess->clt = clt; +- sess->max_pages_per_mr = RTRS_MAX_SEGMENTS; +- init_waitqueue_head(&sess->state_wq); +- sess->state = RTRS_CLT_CONNECTING; +- atomic_set(&sess->connected_cnt, 0); +- INIT_WORK(&sess->close_work, rtrs_clt_close_work); +- INIT_DELAYED_WORK(&sess->reconnect_dwork, rtrs_clt_reconnect_work); +- rtrs_clt_init_hb(sess); +- +- sess->mp_skip_entry = alloc_percpu(typeof(*sess->mp_skip_entry)); +- if (!sess->mp_skip_entry) ++ strscpy(clt_path->s.sessname, clt->sessname, ++ sizeof(clt_path->s.sessname)); ++ clt_path->clt = clt; ++ clt_path->max_pages_per_mr = RTRS_MAX_SEGMENTS; ++ init_waitqueue_head(&clt_path->state_wq); ++ clt_path->state = RTRS_CLT_CONNECTING; ++ atomic_set(&clt_path->connected_cnt, 0); ++ INIT_WORK(&clt_path->close_work, rtrs_clt_close_work); ++ INIT_DELAYED_WORK(&clt_path->reconnect_dwork, rtrs_clt_reconnect_work); ++ rtrs_clt_init_hb(clt_path); ++ ++ clt_path->mp_skip_entry = alloc_percpu(typeof(*clt_path->mp_skip_entry)); ++ if (!clt_path->mp_skip_entry) + goto err_free_stats; + + for_each_possible_cpu(cpu) +- INIT_LIST_HEAD(per_cpu_ptr(sess->mp_skip_entry, cpu)); ++ INIT_LIST_HEAD(per_cpu_ptr(clt_path->mp_skip_entry, cpu)); + +- err = rtrs_clt_init_stats(sess->stats); ++ err = rtrs_clt_init_stats(clt_path->stats); + if (err) + goto err_free_percpu; + +- return sess; ++ return clt_path; + + err_free_percpu: +- free_percpu(sess->mp_skip_entry); ++ free_percpu(clt_path->mp_skip_entry); + err_free_stats: +- kfree(sess->stats); ++ kfree(clt_path->stats); + err_free_con: +- kfree(sess->s.con); +-err_free_sess: +- kfree(sess); ++ kfree(clt_path->s.con); ++err_free_path: ++ kfree(clt_path); + err: + return ERR_PTR(err); + } + +-void free_sess(struct rtrs_clt_sess *sess) ++void free_path(struct rtrs_clt_path *clt_path) + { +- free_percpu(sess->mp_skip_entry); +- mutex_destroy(&sess->init_mutex); +- kfree(sess->s.con); +- kfree(sess->rbufs); +- kfree(sess); ++ free_percpu(clt_path->mp_skip_entry); ++ mutex_destroy(&clt_path->init_mutex); ++ kfree(clt_path->s.con); ++ kfree(clt_path->rbufs); ++ kfree(clt_path); + } + +-static int create_con(struct rtrs_clt_sess *sess, unsigned int cid) ++static int create_con(struct rtrs_clt_path *clt_path, unsigned int cid) + { + struct rtrs_clt_con *con; + +@@ -1601,28 +1607,28 @@ static int create_con(struct rtrs_clt_sess *sess, unsigned int cid) + /* Map first two connections to the first CPU */ + con->cpu = (cid ? cid - 1 : 0) % nr_cpu_ids; + con->c.cid = cid; +- con->c.sess = &sess->s; ++ con->c.path = &clt_path->s; + /* Align with srv, init as 1 */ + atomic_set(&con->c.wr_cnt, 1); + mutex_init(&con->con_mutex); + +- sess->s.con[cid] = &con->c; ++ clt_path->s.con[cid] = &con->c; + + return 0; + } + + static void destroy_con(struct rtrs_clt_con *con) + { +- struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); ++ struct rtrs_clt_path *clt_path = to_clt_path(con->c.path); + +- sess->s.con[con->c.cid] = NULL; ++ clt_path->s.con[con->c.cid] = NULL; + mutex_destroy(&con->con_mutex); + kfree(con); + } + + static int create_con_cq_qp(struct rtrs_clt_con *con) + { +- struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); ++ struct rtrs_clt_path *clt_path = to_clt_path(con->c.path); + u32 max_send_wr, max_recv_wr, cq_num, max_send_sge, wr_limit; + int err, cq_vector; + struct rtrs_msg_rkey_rsp *rsp; +@@ -1631,7 +1637,7 @@ static int create_con_cq_qp(struct rtrs_clt_con *con) + if (con->c.cid == 0) { + max_send_sge = 1; + /* We must be the first here */ +- if (WARN_ON(sess->s.dev)) ++ if (WARN_ON(clt_path->s.dev)) + return -EINVAL; + + /* +@@ -1639,16 +1645,16 @@ static int create_con_cq_qp(struct rtrs_clt_con *con) + * Be careful not to close user connection before ib dev + * is gracefully put. + */ +- sess->s.dev = rtrs_ib_dev_find_or_add(con->c.cm_id->device, ++ clt_path->s.dev = rtrs_ib_dev_find_or_add(con->c.cm_id->device, + &dev_pd); +- if (!sess->s.dev) { +- rtrs_wrn(sess->clt, ++ if (!clt_path->s.dev) { ++ rtrs_wrn(clt_path->clt, + "rtrs_ib_dev_find_get_or_add(): no memory\n"); + return -ENOMEM; + } +- sess->s.dev_ref = 1; +- query_fast_reg_mode(sess); +- wr_limit = sess->s.dev->ib_dev->attrs.max_qp_wr; ++ clt_path->s.dev_ref = 1; ++ query_fast_reg_mode(clt_path); ++ wr_limit = clt_path->s.dev->ib_dev->attrs.max_qp_wr; + /* + * Two (request + registration) completion for send + * Two for recv if always_invalidate is set on server +@@ -1665,27 +1671,28 @@ static int create_con_cq_qp(struct rtrs_clt_con *con) + * This is always true if user connection (cid == 0) is + * established first. + */ +- if (WARN_ON(!sess->s.dev)) ++ if (WARN_ON(!clt_path->s.dev)) + return -EINVAL; +- if (WARN_ON(!sess->queue_depth)) ++ if (WARN_ON(!clt_path->queue_depth)) + return -EINVAL; + +- wr_limit = sess->s.dev->ib_dev->attrs.max_qp_wr; ++ wr_limit = clt_path->s.dev->ib_dev->attrs.max_qp_wr; + /* Shared between connections */ +- sess->s.dev_ref++; ++ clt_path->s.dev_ref++; + max_send_wr = min_t(int, wr_limit, + /* QD * (REQ + RSP + FR REGS or INVS) + drain */ +- sess->queue_depth * 3 + 1); ++ clt_path->queue_depth * 3 + 1); + max_recv_wr = min_t(int, wr_limit, +- sess->queue_depth * 3 + 1); ++ clt_path->queue_depth * 3 + 1); + max_send_sge = 2; + } + atomic_set(&con->c.sq_wr_avail, max_send_wr); + cq_num = max_send_wr + max_recv_wr; + /* alloc iu to recv new rkey reply when server reports flags set */ +- if (sess->flags & RTRS_MSG_NEW_RKEY_F || con->c.cid == 0) { ++ if (clt_path->flags & RTRS_MSG_NEW_RKEY_F || con->c.cid == 0) { + con->rsp_ius = rtrs_iu_alloc(cq_num, sizeof(*rsp), +- GFP_KERNEL, sess->s.dev->ib_dev, ++ GFP_KERNEL, ++ clt_path->s.dev->ib_dev, + DMA_FROM_DEVICE, + rtrs_clt_rdma_done); + if (!con->rsp_ius) +@@ -1693,13 +1700,13 @@ static int create_con_cq_qp(struct rtrs_clt_con *con) + con->queue_num = cq_num; + } + cq_num = max_send_wr + max_recv_wr; +- cq_vector = con->cpu % sess->s.dev->ib_dev->num_comp_vectors; +- if (con->c.cid >= sess->s.irq_con_num) +- err = rtrs_cq_qp_create(&sess->s, &con->c, max_send_sge, ++ cq_vector = con->cpu % clt_path->s.dev->ib_dev->num_comp_vectors; ++ if (con->c.cid >= clt_path->s.irq_con_num) ++ err = rtrs_cq_qp_create(&clt_path->s, &con->c, max_send_sge, + cq_vector, cq_num, max_send_wr, + max_recv_wr, IB_POLL_DIRECT); + else +- err = rtrs_cq_qp_create(&sess->s, &con->c, max_send_sge, ++ err = rtrs_cq_qp_create(&clt_path->s, &con->c, max_send_sge, + cq_vector, cq_num, max_send_wr, + max_recv_wr, IB_POLL_SOFTIRQ); + /* +@@ -1711,7 +1718,7 @@ static int create_con_cq_qp(struct rtrs_clt_con *con) + + static void destroy_con_cq_qp(struct rtrs_clt_con *con) + { +- struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); ++ struct rtrs_clt_path *clt_path = to_clt_path(con->c.path); + + /* + * Be careful here: destroy_con_cq_qp() can be called even +@@ -1720,13 +1727,14 @@ static void destroy_con_cq_qp(struct rtrs_clt_con *con) + lockdep_assert_held(&con->con_mutex); + rtrs_cq_qp_destroy(&con->c); + if (con->rsp_ius) { +- rtrs_iu_free(con->rsp_ius, sess->s.dev->ib_dev, con->queue_num); ++ rtrs_iu_free(con->rsp_ius, clt_path->s.dev->ib_dev, ++ con->queue_num); + con->rsp_ius = NULL; + con->queue_num = 0; + } +- if (sess->s.dev_ref && !--sess->s.dev_ref) { +- rtrs_ib_dev_put(sess->s.dev); +- sess->s.dev = NULL; ++ if (clt_path->s.dev_ref && !--clt_path->s.dev_ref) { ++ rtrs_ib_dev_put(clt_path->s.dev); ++ clt_path->s.dev = NULL; + } + } + +@@ -1745,7 +1753,7 @@ static void destroy_cm(struct rtrs_clt_con *con) + + static int rtrs_rdma_addr_resolved(struct rtrs_clt_con *con) + { +- struct rtrs_sess *s = con->c.sess; ++ struct rtrs_path *s = con->c.path; + int err; + + mutex_lock(&con->con_mutex); +@@ -1764,8 +1772,8 @@ static int rtrs_rdma_addr_resolved(struct rtrs_clt_con *con) + + static int rtrs_rdma_route_resolved(struct rtrs_clt_con *con) + { +- struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); +- struct rtrs_clt *clt = sess->clt; ++ struct rtrs_clt_path *clt_path = to_clt_path(con->c.path); ++ struct rtrs_clt *clt = clt_path->clt; + struct rtrs_msg_conn_req msg; + struct rdma_conn_param param; + +@@ -1782,11 +1790,11 @@ static int rtrs_rdma_route_resolved(struct rtrs_clt_con *con) + .magic = cpu_to_le16(RTRS_MAGIC), + .version = cpu_to_le16(RTRS_PROTO_VER), + .cid = cpu_to_le16(con->c.cid), +- .cid_num = cpu_to_le16(sess->s.con_num), +- .recon_cnt = cpu_to_le16(sess->s.recon_cnt), ++ .cid_num = cpu_to_le16(clt_path->s.con_num), ++ .recon_cnt = cpu_to_le16(clt_path->s.recon_cnt), + }; +- msg.first_conn = sess->for_new_clt ? FIRST_CONN : 0; +- uuid_copy(&msg.sess_uuid, &sess->s.uuid); ++ msg.first_conn = clt_path->for_new_clt ? FIRST_CONN : 0; ++ uuid_copy(&msg.sess_uuid, &clt_path->s.uuid); + uuid_copy(&msg.paths_uuid, &clt->paths_uuid); + + err = rdma_connect_locked(con->c.cm_id, ¶m); +@@ -1799,8 +1807,8 @@ static int rtrs_rdma_route_resolved(struct rtrs_clt_con *con) + static int rtrs_rdma_conn_established(struct rtrs_clt_con *con, + struct rdma_cm_event *ev) + { +- struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); +- struct rtrs_clt *clt = sess->clt; ++ struct rtrs_clt_path *clt_path = to_clt_path(con->c.path); ++ struct rtrs_clt *clt = clt_path->clt; + const struct rtrs_msg_conn_rsp *msg; + u16 version, queue_depth; + int errno; +@@ -1831,31 +1839,32 @@ static int rtrs_rdma_conn_established(struct rtrs_clt_con *con, + if (con->c.cid == 0) { + queue_depth = le16_to_cpu(msg->queue_depth); + +- if (sess->queue_depth > 0 && queue_depth != sess->queue_depth) { ++ if (clt_path->queue_depth > 0 && queue_depth != clt_path->queue_depth) { + rtrs_err(clt, "Error: queue depth changed\n"); + + /* + * Stop any more reconnection attempts + */ +- sess->reconnect_attempts = -1; ++ clt_path->reconnect_attempts = -1; + rtrs_err(clt, + "Disabling auto-reconnect. Trigger a manual reconnect after issue is resolved\n"); + return -ECONNRESET; + } + +- if (!sess->rbufs) { +- sess->rbufs = kcalloc(queue_depth, sizeof(*sess->rbufs), +- GFP_KERNEL); +- if (!sess->rbufs) ++ if (!clt_path->rbufs) { ++ clt_path->rbufs = kcalloc(queue_depth, ++ sizeof(*clt_path->rbufs), ++ GFP_KERNEL); ++ if (!clt_path->rbufs) + return -ENOMEM; + } +- sess->queue_depth = queue_depth; +- sess->s.signal_interval = min_not_zero(queue_depth, ++ clt_path->queue_depth = queue_depth; ++ clt_path->s.signal_interval = min_not_zero(queue_depth, + (unsigned short) SERVICE_CON_QUEUE_DEPTH); +- sess->max_hdr_size = le32_to_cpu(msg->max_hdr_size); +- sess->max_io_size = le32_to_cpu(msg->max_io_size); +- sess->flags = le32_to_cpu(msg->flags); +- sess->chunk_size = sess->max_io_size + sess->max_hdr_size; ++ clt_path->max_hdr_size = le32_to_cpu(msg->max_hdr_size); ++ clt_path->max_io_size = le32_to_cpu(msg->max_io_size); ++ clt_path->flags = le32_to_cpu(msg->flags); ++ clt_path->chunk_size = clt_path->max_io_size + clt_path->max_hdr_size; + + /* + * Global IO size is always a minimum. +@@ -1866,20 +1875,20 @@ static int rtrs_rdma_conn_established(struct rtrs_clt_con *con, + * connections in parallel, use lock. + */ + mutex_lock(&clt->paths_mutex); +- clt->queue_depth = sess->queue_depth; +- clt->max_io_size = min_not_zero(sess->max_io_size, ++ clt->queue_depth = clt_path->queue_depth; ++ clt->max_io_size = min_not_zero(clt_path->max_io_size, + clt->max_io_size); + mutex_unlock(&clt->paths_mutex); + + /* + * Cache the hca_port and hca_name for sysfs + */ +- sess->hca_port = con->c.cm_id->port_num; +- scnprintf(sess->hca_name, sizeof(sess->hca_name), +- sess->s.dev->ib_dev->name); +- sess->s.src_addr = con->c.cm_id->route.addr.src_addr; ++ clt_path->hca_port = con->c.cm_id->port_num; ++ scnprintf(clt_path->hca_name, sizeof(clt_path->hca_name), ++ clt_path->s.dev->ib_dev->name); ++ clt_path->s.src_addr = con->c.cm_id->route.addr.src_addr; + /* set for_new_clt, to allow future reconnect on any path */ +- sess->for_new_clt = 1; ++ clt_path->for_new_clt = 1; + } + + return 0; +@@ -1887,16 +1896,16 @@ static int rtrs_rdma_conn_established(struct rtrs_clt_con *con, + + static inline void flag_success_on_conn(struct rtrs_clt_con *con) + { +- struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); ++ struct rtrs_clt_path *clt_path = to_clt_path(con->c.path); + +- atomic_inc(&sess->connected_cnt); ++ atomic_inc(&clt_path->connected_cnt); + con->cm_err = 1; + } + + static int rtrs_rdma_conn_rejected(struct rtrs_clt_con *con, + struct rdma_cm_event *ev) + { +- struct rtrs_sess *s = con->c.sess; ++ struct rtrs_path *s = con->c.path; + const struct rtrs_msg_conn_rsp *msg; + const char *rej_msg; + int status, errno; +@@ -1924,23 +1933,23 @@ static int rtrs_rdma_conn_rejected(struct rtrs_clt_con *con, + return -ECONNRESET; + } + +-void rtrs_clt_close_conns(struct rtrs_clt_sess *sess, bool wait) ++void rtrs_clt_close_conns(struct rtrs_clt_path *clt_path, bool wait) + { +- if (rtrs_clt_change_state_get_old(sess, RTRS_CLT_CLOSING, NULL)) +- queue_work(rtrs_wq, &sess->close_work); ++ if (rtrs_clt_change_state_get_old(clt_path, RTRS_CLT_CLOSING, NULL)) ++ queue_work(rtrs_wq, &clt_path->close_work); + if (wait) +- flush_work(&sess->close_work); ++ flush_work(&clt_path->close_work); + } + + static inline void flag_error_on_conn(struct rtrs_clt_con *con, int cm_err) + { + if (con->cm_err == 1) { +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + +- sess = to_clt_sess(con->c.sess); +- if (atomic_dec_and_test(&sess->connected_cnt)) ++ clt_path = to_clt_path(con->c.path); ++ if (atomic_dec_and_test(&clt_path->connected_cnt)) + +- wake_up(&sess->state_wq); ++ wake_up(&clt_path->state_wq); + } + con->cm_err = cm_err; + } +@@ -1949,8 +1958,8 @@ static int rtrs_clt_rdma_cm_handler(struct rdma_cm_id *cm_id, + struct rdma_cm_event *ev) + { + struct rtrs_clt_con *con = cm_id->context; +- struct rtrs_sess *s = con->c.sess; +- struct rtrs_clt_sess *sess = to_clt_sess(s); ++ struct rtrs_path *s = con->c.path; ++ struct rtrs_clt_path *clt_path = to_clt_path(s); + int cm_err = 0; + + switch (ev->event) { +@@ -1968,7 +1977,7 @@ static int rtrs_clt_rdma_cm_handler(struct rdma_cm_id *cm_id, + * i.e. wake up without state change, but we set cm_err. + */ + flag_success_on_conn(con); +- wake_up(&sess->state_wq); ++ wake_up(&clt_path->state_wq); + return 0; + } + break; +@@ -1997,7 +2006,7 @@ static int rtrs_clt_rdma_cm_handler(struct rdma_cm_id *cm_id, + /* + * Device removal is a special case. Queue close and return 0. + */ +- rtrs_clt_close_conns(sess, false); ++ rtrs_clt_close_conns(clt_path, false); + return 0; + default: + rtrs_err(s, "Unexpected RDMA CM error (CM event: %s, err: %d)\n", +@@ -2020,13 +2029,13 @@ static int rtrs_clt_rdma_cm_handler(struct rdma_cm_id *cm_id, + + static int create_cm(struct rtrs_clt_con *con) + { +- struct rtrs_sess *s = con->c.sess; +- struct rtrs_clt_sess *sess = to_clt_sess(s); ++ struct rtrs_path *s = con->c.path; ++ struct rtrs_clt_path *clt_path = to_clt_path(s); + struct rdma_cm_id *cm_id; + int err; + + cm_id = rdma_create_id(&init_net, rtrs_clt_rdma_cm_handler, con, +- sess->s.dst_addr.ss_family == AF_IB ? ++ clt_path->s.dst_addr.ss_family == AF_IB ? + RDMA_PS_IB : RDMA_PS_TCP, IB_QPT_RC); + if (IS_ERR(cm_id)) { + err = PTR_ERR(cm_id); +@@ -2042,8 +2051,8 @@ static int create_cm(struct rtrs_clt_con *con) + rtrs_err(s, "Set address reuse failed, err: %d\n", err); + goto destroy_cm; + } +- err = rdma_resolve_addr(cm_id, (struct sockaddr *)&sess->s.src_addr, +- (struct sockaddr *)&sess->s.dst_addr, ++ err = rdma_resolve_addr(cm_id, (struct sockaddr *)&clt_path->s.src_addr, ++ (struct sockaddr *)&clt_path->s.dst_addr, + RTRS_CONNECT_TIMEOUT_MS); + if (err) { + rtrs_err(s, "Failed to resolve address, err: %d\n", err); +@@ -2055,8 +2064,8 @@ static int create_cm(struct rtrs_clt_con *con) + * or session state was really changed to error by device removal. + */ + err = wait_event_interruptible_timeout( +- sess->state_wq, +- con->cm_err || sess->state != RTRS_CLT_CONNECTING, ++ clt_path->state_wq, ++ con->cm_err || clt_path->state != RTRS_CLT_CONNECTING, + msecs_to_jiffies(RTRS_CONNECT_TIMEOUT_MS)); + if (err == 0 || err == -ERESTARTSYS) { + if (err == 0) +@@ -2068,7 +2077,7 @@ static int create_cm(struct rtrs_clt_con *con) + err = con->cm_err; + goto errr; + } +- if (READ_ONCE(sess->state) != RTRS_CLT_CONNECTING) { ++ if (READ_ONCE(clt_path->state) != RTRS_CLT_CONNECTING) { + /* Device removal */ + err = -ECONNABORTED; + goto errr; +@@ -2087,9 +2096,9 @@ destroy_cm: + return err; + } + +-static void rtrs_clt_sess_up(struct rtrs_clt_sess *sess) ++static void rtrs_clt_path_up(struct rtrs_clt_path *clt_path) + { +- struct rtrs_clt *clt = sess->clt; ++ struct rtrs_clt *clt = clt_path->clt; + int up; + + /* +@@ -2113,19 +2122,19 @@ static void rtrs_clt_sess_up(struct rtrs_clt_sess *sess) + mutex_unlock(&clt->paths_ev_mutex); + + /* Mark session as established */ +- sess->established = true; +- sess->reconnect_attempts = 0; +- sess->stats->reconnects.successful_cnt++; ++ clt_path->established = true; ++ clt_path->reconnect_attempts = 0; ++ clt_path->stats->reconnects.successful_cnt++; + } + +-static void rtrs_clt_sess_down(struct rtrs_clt_sess *sess) ++static void rtrs_clt_path_down(struct rtrs_clt_path *clt_path) + { +- struct rtrs_clt *clt = sess->clt; ++ struct rtrs_clt *clt = clt_path->clt; + +- if (!sess->established) ++ if (!clt_path->established) + return; + +- sess->established = false; ++ clt_path->established = false; + mutex_lock(&clt->paths_ev_mutex); + WARN_ON(!clt->paths_up); + if (--clt->paths_up == 0) +@@ -2133,19 +2142,19 @@ static void rtrs_clt_sess_down(struct rtrs_clt_sess *sess) + mutex_unlock(&clt->paths_ev_mutex); + } + +-static void rtrs_clt_stop_and_destroy_conns(struct rtrs_clt_sess *sess) ++static void rtrs_clt_stop_and_destroy_conns(struct rtrs_clt_path *clt_path) + { + struct rtrs_clt_con *con; + unsigned int cid; + +- WARN_ON(READ_ONCE(sess->state) == RTRS_CLT_CONNECTED); ++ WARN_ON(READ_ONCE(clt_path->state) == RTRS_CLT_CONNECTED); + + /* + * Possible race with rtrs_clt_open(), when DEVICE_REMOVAL comes + * exactly in between. Start destroying after it finishes. + */ +- mutex_lock(&sess->init_mutex); +- mutex_unlock(&sess->init_mutex); ++ mutex_lock(&clt_path->init_mutex); ++ mutex_unlock(&clt_path->init_mutex); + + /* + * All IO paths must observe !CONNECTED state before we +@@ -2153,7 +2162,7 @@ static void rtrs_clt_stop_and_destroy_conns(struct rtrs_clt_sess *sess) + */ + synchronize_rcu(); + +- rtrs_stop_hb(&sess->s); ++ rtrs_stop_hb(&clt_path->s); + + /* + * The order it utterly crucial: firstly disconnect and complete all +@@ -2162,15 +2171,15 @@ static void rtrs_clt_stop_and_destroy_conns(struct rtrs_clt_sess *sess) + * eventually notify upper layer about session disconnection. + */ + +- for (cid = 0; cid < sess->s.con_num; cid++) { +- if (!sess->s.con[cid]) ++ for (cid = 0; cid < clt_path->s.con_num; cid++) { ++ if (!clt_path->s.con[cid]) + break; +- con = to_clt_con(sess->s.con[cid]); ++ con = to_clt_con(clt_path->s.con[cid]); + stop_cm(con); + } +- fail_all_outstanding_reqs(sess); +- free_sess_reqs(sess); +- rtrs_clt_sess_down(sess); ++ fail_all_outstanding_reqs(clt_path); ++ free_path_reqs(clt_path); ++ rtrs_clt_path_down(clt_path); + + /* + * Wait for graceful shutdown, namely when peer side invokes +@@ -2180,13 +2189,14 @@ static void rtrs_clt_stop_and_destroy_conns(struct rtrs_clt_sess *sess) + * since CM does not fire anything. That is fine, we are not in + * hurry. + */ +- wait_event_timeout(sess->state_wq, !atomic_read(&sess->connected_cnt), ++ wait_event_timeout(clt_path->state_wq, ++ !atomic_read(&clt_path->connected_cnt), + msecs_to_jiffies(RTRS_CONNECT_TIMEOUT_MS)); + +- for (cid = 0; cid < sess->s.con_num; cid++) { +- if (!sess->s.con[cid]) ++ for (cid = 0; cid < clt_path->s.con_num; cid++) { ++ if (!clt_path->s.con[cid]) + break; +- con = to_clt_con(sess->s.con[cid]); ++ con = to_clt_con(clt_path->s.con[cid]); + mutex_lock(&con->con_mutex); + destroy_con_cq_qp(con); + mutex_unlock(&con->con_mutex); +@@ -2195,26 +2205,26 @@ static void rtrs_clt_stop_and_destroy_conns(struct rtrs_clt_sess *sess) + } + } + +-static inline bool xchg_sessions(struct rtrs_clt_sess __rcu **rcu_ppcpu_path, +- struct rtrs_clt_sess *sess, +- struct rtrs_clt_sess *next) ++static inline bool xchg_paths(struct rtrs_clt_path __rcu **rcu_ppcpu_path, ++ struct rtrs_clt_path *clt_path, ++ struct rtrs_clt_path *next) + { +- struct rtrs_clt_sess **ppcpu_path; ++ struct rtrs_clt_path **ppcpu_path; + + /* Call cmpxchg() without sparse warnings */ + ppcpu_path = (typeof(ppcpu_path))rcu_ppcpu_path; +- return sess == cmpxchg(ppcpu_path, sess, next); ++ return clt_path == cmpxchg(ppcpu_path, clt_path, next); + } + +-static void rtrs_clt_remove_path_from_arr(struct rtrs_clt_sess *sess) ++static void rtrs_clt_remove_path_from_arr(struct rtrs_clt_path *clt_path) + { +- struct rtrs_clt *clt = sess->clt; +- struct rtrs_clt_sess *next; ++ struct rtrs_clt *clt = clt_path->clt; ++ struct rtrs_clt_path *next; + bool wait_for_grace = false; + int cpu; + + mutex_lock(&clt->paths_mutex); +- list_del_rcu(&sess->s.entry); ++ list_del_rcu(&clt_path->s.entry); + + /* Make sure everybody observes path removal. */ + synchronize_rcu(); +@@ -2255,8 +2265,7 @@ static void rtrs_clt_remove_path_from_arr(struct rtrs_clt_sess *sess) + * removed. If @sess is the last element, then @next is NULL. + */ + rcu_read_lock(); +- next = list_next_or_null_rr_rcu(&clt->paths_list, &sess->s.entry, +- typeof(*next), s.entry); ++ next = rtrs_clt_get_next_path_or_null(&clt->paths_list, clt_path); + rcu_read_unlock(); + + /* +@@ -2264,11 +2273,11 @@ static void rtrs_clt_remove_path_from_arr(struct rtrs_clt_sess *sess) + * removed, so change the pointer manually. + */ + for_each_possible_cpu(cpu) { +- struct rtrs_clt_sess __rcu **ppcpu_path; ++ struct rtrs_clt_path __rcu **ppcpu_path; + + ppcpu_path = per_cpu_ptr(clt->pcpu_path, cpu); + if (rcu_dereference_protected(*ppcpu_path, +- lockdep_is_held(&clt->paths_mutex)) != sess) ++ lockdep_is_held(&clt->paths_mutex)) != clt_path) + /* + * synchronize_rcu() was called just after deleting + * entry from the list, thus IO code path cannot +@@ -2281,7 +2290,7 @@ static void rtrs_clt_remove_path_from_arr(struct rtrs_clt_sess *sess) + * We race with IO code path, which also changes pointer, + * thus we have to be careful not to overwrite it. + */ +- if (xchg_sessions(ppcpu_path, sess, next)) ++ if (xchg_paths(ppcpu_path, clt_path, next)) + /* + * @ppcpu_path was successfully replaced with @next, + * that means that someone could also pick up the +@@ -2296,29 +2305,29 @@ static void rtrs_clt_remove_path_from_arr(struct rtrs_clt_sess *sess) + mutex_unlock(&clt->paths_mutex); + } + +-static void rtrs_clt_add_path_to_arr(struct rtrs_clt_sess *sess) ++static void rtrs_clt_add_path_to_arr(struct rtrs_clt_path *clt_path) + { +- struct rtrs_clt *clt = sess->clt; ++ struct rtrs_clt *clt = clt_path->clt; + + mutex_lock(&clt->paths_mutex); + clt->paths_num++; + +- list_add_tail_rcu(&sess->s.entry, &clt->paths_list); ++ list_add_tail_rcu(&clt_path->s.entry, &clt->paths_list); + mutex_unlock(&clt->paths_mutex); + } + + static void rtrs_clt_close_work(struct work_struct *work) + { +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + +- sess = container_of(work, struct rtrs_clt_sess, close_work); ++ clt_path = container_of(work, struct rtrs_clt_path, close_work); + +- cancel_delayed_work_sync(&sess->reconnect_dwork); +- rtrs_clt_stop_and_destroy_conns(sess); +- rtrs_clt_change_state_get_old(sess, RTRS_CLT_CLOSED, NULL); ++ cancel_delayed_work_sync(&clt_path->reconnect_dwork); ++ rtrs_clt_stop_and_destroy_conns(clt_path); ++ rtrs_clt_change_state_get_old(clt_path, RTRS_CLT_CLOSED, NULL); + } + +-static int init_conns(struct rtrs_clt_sess *sess) ++static int init_conns(struct rtrs_clt_path *clt_path) + { + unsigned int cid; + int err; +@@ -2328,31 +2337,31 @@ static int init_conns(struct rtrs_clt_sess *sess) + * to avoid clashes with previous sessions not yet closed + * sessions on a server side. + */ +- sess->s.recon_cnt++; ++ clt_path->s.recon_cnt++; + + /* Establish all RDMA connections */ +- for (cid = 0; cid < sess->s.con_num; cid++) { +- err = create_con(sess, cid); ++ for (cid = 0; cid < clt_path->s.con_num; cid++) { ++ err = create_con(clt_path, cid); + if (err) + goto destroy; + +- err = create_cm(to_clt_con(sess->s.con[cid])); ++ err = create_cm(to_clt_con(clt_path->s.con[cid])); + if (err) { +- destroy_con(to_clt_con(sess->s.con[cid])); ++ destroy_con(to_clt_con(clt_path->s.con[cid])); + goto destroy; + } + } +- err = alloc_sess_reqs(sess); ++ err = alloc_path_reqs(clt_path); + if (err) + goto destroy; + +- rtrs_start_hb(&sess->s); ++ rtrs_start_hb(&clt_path->s); + + return 0; + + destroy: + while (cid--) { +- struct rtrs_clt_con *con = to_clt_con(sess->s.con[cid]); ++ struct rtrs_clt_con *con = to_clt_con(clt_path->s.con[cid]); + + stop_cm(con); + +@@ -2367,7 +2376,7 @@ destroy: + * doing rdma_resolve_addr(), switch to CONNECTION_ERR state + * manually to keep reconnecting. + */ +- rtrs_clt_change_state_get_old(sess, RTRS_CLT_CONNECTING_ERR, NULL); ++ rtrs_clt_change_state_get_old(clt_path, RTRS_CLT_CONNECTING_ERR, NULL); + + return err; + } +@@ -2375,31 +2384,32 @@ destroy: + static void rtrs_clt_info_req_done(struct ib_cq *cq, struct ib_wc *wc) + { + struct rtrs_clt_con *con = to_clt_con(wc->qp->qp_context); +- struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); ++ struct rtrs_clt_path *clt_path = to_clt_path(con->c.path); + struct rtrs_iu *iu; + + iu = container_of(wc->wr_cqe, struct rtrs_iu, cqe); +- rtrs_iu_free(iu, sess->s.dev->ib_dev, 1); ++ rtrs_iu_free(iu, clt_path->s.dev->ib_dev, 1); + + if (wc->status != IB_WC_SUCCESS) { +- rtrs_err(sess->clt, "Sess info request send failed: %s\n", ++ rtrs_err(clt_path->clt, "Path info request send failed: %s\n", + ib_wc_status_msg(wc->status)); +- rtrs_clt_change_state_get_old(sess, RTRS_CLT_CONNECTING_ERR, NULL); ++ rtrs_clt_change_state_get_old(clt_path, RTRS_CLT_CONNECTING_ERR, NULL); + return; + } + + rtrs_clt_update_wc_stats(con); + } + +-static int process_info_rsp(struct rtrs_clt_sess *sess, ++static int process_info_rsp(struct rtrs_clt_path *clt_path, + const struct rtrs_msg_info_rsp *msg) + { + unsigned int sg_cnt, total_len; + int i, sgi; + + sg_cnt = le16_to_cpu(msg->sg_cnt); +- if (!sg_cnt || (sess->queue_depth % sg_cnt)) { +- rtrs_err(sess->clt, "Incorrect sg_cnt %d, is not multiple\n", ++ if (!sg_cnt || (clt_path->queue_depth % sg_cnt)) { ++ rtrs_err(clt_path->clt, ++ "Incorrect sg_cnt %d, is not multiple\n", + sg_cnt); + return -EINVAL; + } +@@ -2408,15 +2418,15 @@ static int process_info_rsp(struct rtrs_clt_sess *sess, + * Check if IB immediate data size is enough to hold the mem_id and + * the offset inside the memory chunk. + */ +- if ((ilog2(sg_cnt - 1) + 1) + (ilog2(sess->chunk_size - 1) + 1) > ++ if ((ilog2(sg_cnt - 1) + 1) + (ilog2(clt_path->chunk_size - 1) + 1) > + MAX_IMM_PAYL_BITS) { +- rtrs_err(sess->clt, ++ rtrs_err(clt_path->clt, + "RDMA immediate size (%db) not enough to encode %d buffers of size %dB\n", +- MAX_IMM_PAYL_BITS, sg_cnt, sess->chunk_size); ++ MAX_IMM_PAYL_BITS, sg_cnt, clt_path->chunk_size); + return -EINVAL; + } + total_len = 0; +- for (sgi = 0, i = 0; sgi < sg_cnt && i < sess->queue_depth; sgi++) { ++ for (sgi = 0, i = 0; sgi < sg_cnt && i < clt_path->queue_depth; sgi++) { + const struct rtrs_sg_desc *desc = &msg->desc[sgi]; + u32 len, rkey; + u64 addr; +@@ -2427,26 +2437,28 @@ static int process_info_rsp(struct rtrs_clt_sess *sess, + + total_len += len; + +- if (!len || (len % sess->chunk_size)) { +- rtrs_err(sess->clt, "Incorrect [%d].len %d\n", sgi, ++ if (!len || (len % clt_path->chunk_size)) { ++ rtrs_err(clt_path->clt, "Incorrect [%d].len %d\n", ++ sgi, + len); + return -EINVAL; + } +- for ( ; len && i < sess->queue_depth; i++) { +- sess->rbufs[i].addr = addr; +- sess->rbufs[i].rkey = rkey; ++ for ( ; len && i < clt_path->queue_depth; i++) { ++ clt_path->rbufs[i].addr = addr; ++ clt_path->rbufs[i].rkey = rkey; + +- len -= sess->chunk_size; +- addr += sess->chunk_size; ++ len -= clt_path->chunk_size; ++ addr += clt_path->chunk_size; + } + } + /* Sanity check */ +- if (sgi != sg_cnt || i != sess->queue_depth) { +- rtrs_err(sess->clt, "Incorrect sg vector, not fully mapped\n"); ++ if (sgi != sg_cnt || i != clt_path->queue_depth) { ++ rtrs_err(clt_path->clt, ++ "Incorrect sg vector, not fully mapped\n"); + return -EINVAL; + } +- if (total_len != sess->chunk_size * sess->queue_depth) { +- rtrs_err(sess->clt, "Incorrect total_len %d\n", total_len); ++ if (total_len != clt_path->chunk_size * clt_path->queue_depth) { ++ rtrs_err(clt_path->clt, "Incorrect total_len %d\n", total_len); + return -EINVAL; + } + +@@ -2456,7 +2468,7 @@ static int process_info_rsp(struct rtrs_clt_sess *sess, + static void rtrs_clt_info_rsp_done(struct ib_cq *cq, struct ib_wc *wc) + { + struct rtrs_clt_con *con = to_clt_con(wc->qp->qp_context); +- struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); ++ struct rtrs_clt_path *clt_path = to_clt_path(con->c.path); + struct rtrs_msg_info_rsp *msg; + enum rtrs_clt_state state; + struct rtrs_iu *iu; +@@ -2468,37 +2480,37 @@ static void rtrs_clt_info_rsp_done(struct ib_cq *cq, struct ib_wc *wc) + WARN_ON(con->c.cid); + iu = container_of(wc->wr_cqe, struct rtrs_iu, cqe); + if (wc->status != IB_WC_SUCCESS) { +- rtrs_err(sess->clt, "Sess info response recv failed: %s\n", ++ rtrs_err(clt_path->clt, "Path info response recv failed: %s\n", + ib_wc_status_msg(wc->status)); + goto out; + } + WARN_ON(wc->opcode != IB_WC_RECV); + + if (wc->byte_len < sizeof(*msg)) { +- rtrs_err(sess->clt, "Sess info response is malformed: size %d\n", ++ rtrs_err(clt_path->clt, "Path info response is malformed: size %d\n", + wc->byte_len); + goto out; + } +- ib_dma_sync_single_for_cpu(sess->s.dev->ib_dev, iu->dma_addr, ++ ib_dma_sync_single_for_cpu(clt_path->s.dev->ib_dev, iu->dma_addr, + iu->size, DMA_FROM_DEVICE); + msg = iu->buf; + if (le16_to_cpu(msg->type) != RTRS_MSG_INFO_RSP) { +- rtrs_err(sess->clt, "Sess info response is malformed: type %d\n", ++ rtrs_err(clt_path->clt, "Path info response is malformed: type %d\n", + le16_to_cpu(msg->type)); + goto out; + } + rx_sz = sizeof(*msg); + rx_sz += sizeof(msg->desc[0]) * le16_to_cpu(msg->sg_cnt); + if (wc->byte_len < rx_sz) { +- rtrs_err(sess->clt, "Sess info response is malformed: size %d\n", ++ rtrs_err(clt_path->clt, "Path info response is malformed: size %d\n", + wc->byte_len); + goto out; + } +- err = process_info_rsp(sess, msg); ++ err = process_info_rsp(clt_path, msg); + if (err) + goto out; + +- err = post_recv_sess(sess); ++ err = post_recv_path(clt_path); + if (err) + goto out; + +@@ -2506,25 +2518,25 @@ static void rtrs_clt_info_rsp_done(struct ib_cq *cq, struct ib_wc *wc) + + out: + rtrs_clt_update_wc_stats(con); +- rtrs_iu_free(iu, sess->s.dev->ib_dev, 1); +- rtrs_clt_change_state_get_old(sess, state, NULL); ++ rtrs_iu_free(iu, clt_path->s.dev->ib_dev, 1); ++ rtrs_clt_change_state_get_old(clt_path, state, NULL); + } + +-static int rtrs_send_sess_info(struct rtrs_clt_sess *sess) ++static int rtrs_send_path_info(struct rtrs_clt_path *clt_path) + { +- struct rtrs_clt_con *usr_con = to_clt_con(sess->s.con[0]); ++ struct rtrs_clt_con *usr_con = to_clt_con(clt_path->s.con[0]); + struct rtrs_msg_info_req *msg; + struct rtrs_iu *tx_iu, *rx_iu; + size_t rx_sz; + int err; + + rx_sz = sizeof(struct rtrs_msg_info_rsp); +- rx_sz += sizeof(struct rtrs_sg_desc) * sess->queue_depth; ++ rx_sz += sizeof(struct rtrs_sg_desc) * clt_path->queue_depth; + + tx_iu = rtrs_iu_alloc(1, sizeof(struct rtrs_msg_info_req), GFP_KERNEL, +- sess->s.dev->ib_dev, DMA_TO_DEVICE, ++ clt_path->s.dev->ib_dev, DMA_TO_DEVICE, + rtrs_clt_info_req_done); +- rx_iu = rtrs_iu_alloc(1, rx_sz, GFP_KERNEL, sess->s.dev->ib_dev, ++ rx_iu = rtrs_iu_alloc(1, rx_sz, GFP_KERNEL, clt_path->s.dev->ib_dev, + DMA_FROM_DEVICE, rtrs_clt_info_rsp_done); + if (!tx_iu || !rx_iu) { + err = -ENOMEM; +@@ -2533,33 +2545,34 @@ static int rtrs_send_sess_info(struct rtrs_clt_sess *sess) + /* Prepare for getting info response */ + err = rtrs_iu_post_recv(&usr_con->c, rx_iu); + if (err) { +- rtrs_err(sess->clt, "rtrs_iu_post_recv(), err: %d\n", err); ++ rtrs_err(clt_path->clt, "rtrs_iu_post_recv(), err: %d\n", err); + goto out; + } + rx_iu = NULL; + + msg = tx_iu->buf; + msg->type = cpu_to_le16(RTRS_MSG_INFO_REQ); +- memcpy(msg->sessname, sess->s.sessname, sizeof(msg->sessname)); ++ memcpy(msg->pathname, clt_path->s.sessname, sizeof(msg->pathname)); + +- ib_dma_sync_single_for_device(sess->s.dev->ib_dev, tx_iu->dma_addr, ++ ib_dma_sync_single_for_device(clt_path->s.dev->ib_dev, ++ tx_iu->dma_addr, + tx_iu->size, DMA_TO_DEVICE); + + /* Send info request */ + err = rtrs_iu_post_send(&usr_con->c, tx_iu, sizeof(*msg), NULL); + if (err) { +- rtrs_err(sess->clt, "rtrs_iu_post_send(), err: %d\n", err); ++ rtrs_err(clt_path->clt, "rtrs_iu_post_send(), err: %d\n", err); + goto out; + } + tx_iu = NULL; + + /* Wait for state change */ +- wait_event_interruptible_timeout(sess->state_wq, +- sess->state != RTRS_CLT_CONNECTING, ++ wait_event_interruptible_timeout(clt_path->state_wq, ++ clt_path->state != RTRS_CLT_CONNECTING, + msecs_to_jiffies( + RTRS_CONNECT_TIMEOUT_MS)); +- if (READ_ONCE(sess->state) != RTRS_CLT_CONNECTED) { +- if (READ_ONCE(sess->state) == RTRS_CLT_CONNECTING_ERR) ++ if (READ_ONCE(clt_path->state) != RTRS_CLT_CONNECTED) { ++ if (READ_ONCE(clt_path->state) == RTRS_CLT_CONNECTING_ERR) + err = -ECONNRESET; + else + err = -ETIMEDOUT; +@@ -2567,82 +2580,82 @@ static int rtrs_send_sess_info(struct rtrs_clt_sess *sess) + + out: + if (tx_iu) +- rtrs_iu_free(tx_iu, sess->s.dev->ib_dev, 1); ++ rtrs_iu_free(tx_iu, clt_path->s.dev->ib_dev, 1); + if (rx_iu) +- rtrs_iu_free(rx_iu, sess->s.dev->ib_dev, 1); ++ rtrs_iu_free(rx_iu, clt_path->s.dev->ib_dev, 1); + if (err) + /* If we've never taken async path because of malloc problems */ +- rtrs_clt_change_state_get_old(sess, RTRS_CLT_CONNECTING_ERR, NULL); ++ rtrs_clt_change_state_get_old(clt_path, ++ RTRS_CLT_CONNECTING_ERR, NULL); + + return err; + } + + /** +- * init_sess() - establishes all session connections and does handshake +- * @sess: client session. ++ * init_path() - establishes all path connections and does handshake ++ * @clt_path: client path. + * In case of error full close or reconnect procedure should be taken, + * because reconnect or close async works can be started. + */ +-static int init_sess(struct rtrs_clt_sess *sess) ++static int init_path(struct rtrs_clt_path *clt_path) + { + int err; + char str[NAME_MAX]; + struct rtrs_addr path = { +- .src = &sess->s.src_addr, +- .dst = &sess->s.dst_addr, ++ .src = &clt_path->s.src_addr, ++ .dst = &clt_path->s.dst_addr, + }; + + rtrs_addr_to_str(&path, str, sizeof(str)); + +- mutex_lock(&sess->init_mutex); +- err = init_conns(sess); ++ mutex_lock(&clt_path->init_mutex); ++ err = init_conns(clt_path); + if (err) { +- rtrs_err(sess->clt, ++ rtrs_err(clt_path->clt, + "init_conns() failed: err=%d path=%s [%s:%u]\n", err, +- str, sess->hca_name, sess->hca_port); ++ str, clt_path->hca_name, clt_path->hca_port); + goto out; + } +- err = rtrs_send_sess_info(sess); ++ err = rtrs_send_path_info(clt_path); + if (err) { +- rtrs_err( +- sess->clt, +- "rtrs_send_sess_info() failed: err=%d path=%s [%s:%u]\n", +- err, str, sess->hca_name, sess->hca_port); ++ rtrs_err(clt_path->clt, ++ "rtrs_send_path_info() failed: err=%d path=%s [%s:%u]\n", ++ err, str, clt_path->hca_name, clt_path->hca_port); + goto out; + } +- rtrs_clt_sess_up(sess); ++ rtrs_clt_path_up(clt_path); + out: +- mutex_unlock(&sess->init_mutex); ++ mutex_unlock(&clt_path->init_mutex); + + return err; + } + + static void rtrs_clt_reconnect_work(struct work_struct *work) + { +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + struct rtrs_clt *clt; + unsigned int delay_ms; + int err; + +- sess = container_of(to_delayed_work(work), struct rtrs_clt_sess, +- reconnect_dwork); +- clt = sess->clt; ++ clt_path = container_of(to_delayed_work(work), struct rtrs_clt_path, ++ reconnect_dwork); ++ clt = clt_path->clt; + +- if (READ_ONCE(sess->state) != RTRS_CLT_RECONNECTING) ++ if (READ_ONCE(clt_path->state) != RTRS_CLT_RECONNECTING) + return; + +- if (sess->reconnect_attempts >= clt->max_reconnect_attempts) { +- /* Close a session completely if max attempts is reached */ +- rtrs_clt_close_conns(sess, false); ++ if (clt_path->reconnect_attempts >= clt->max_reconnect_attempts) { ++ /* Close a path completely if max attempts is reached */ ++ rtrs_clt_close_conns(clt_path, false); + return; + } +- sess->reconnect_attempts++; ++ clt_path->reconnect_attempts++; + + /* Stop everything */ +- rtrs_clt_stop_and_destroy_conns(sess); ++ rtrs_clt_stop_and_destroy_conns(clt_path); + msleep(RTRS_RECONNECT_BACKOFF); +- if (rtrs_clt_change_state_get_old(sess, RTRS_CLT_CONNECTING, NULL)) { +- err = init_sess(sess); ++ if (rtrs_clt_change_state_get_old(clt_path, RTRS_CLT_CONNECTING, NULL)) { ++ err = init_path(clt_path); + if (err) + goto reconnect_again; + } +@@ -2650,10 +2663,10 @@ static void rtrs_clt_reconnect_work(struct work_struct *work) + return; + + reconnect_again: +- if (rtrs_clt_change_state_get_old(sess, RTRS_CLT_RECONNECTING, NULL)) { +- sess->stats->reconnects.fail_cnt++; ++ if (rtrs_clt_change_state_get_old(clt_path, RTRS_CLT_RECONNECTING, NULL)) { ++ clt_path->stats->reconnects.fail_cnt++; + delay_ms = clt->reconnect_delay_sec * 1000; +- queue_delayed_work(rtrs_wq, &sess->reconnect_dwork, ++ queue_delayed_work(rtrs_wq, &clt_path->reconnect_dwork, + msecs_to_jiffies(delay_ms + + prandom_u32() % + RTRS_RECONNECT_SEED)); +@@ -2762,7 +2775,7 @@ static void free_clt(struct rtrs_clt *clt) + } + + /** +- * rtrs_clt_open() - Open a session to an RTRS server ++ * rtrs_clt_open() - Open a path to an RTRS server + * @ops: holds the link event callback and the private pointer. + * @sessname: name of the session + * @paths: Paths to be established defined by their src and dst addresses +@@ -2780,17 +2793,23 @@ static void free_clt(struct rtrs_clt *clt) + * Return a valid pointer on success otherwise PTR_ERR. + */ + struct rtrs_clt *rtrs_clt_open(struct rtrs_clt_ops *ops, +- const char *sessname, ++ const char *pathname, + const struct rtrs_addr *paths, + size_t paths_num, u16 port, + size_t pdu_sz, u8 reconnect_delay_sec, + s16 max_reconnect_attempts, u32 nr_poll_queues) + { +- struct rtrs_clt_sess *sess, *tmp; ++ struct rtrs_clt_path *clt_path, *tmp; + struct rtrs_clt *clt; + int err, i; + +- clt = alloc_clt(sessname, paths_num, port, pdu_sz, ops->priv, ++ if (strchr(pathname, '/') || strchr(pathname, '.')) { ++ pr_err("pathname cannot contain / and .\n"); ++ err = -EINVAL; ++ goto out; ++ } ++ ++ clt = alloc_clt(pathname, paths_num, port, pdu_sz, ops->priv, + ops->link_ev, + reconnect_delay_sec, + max_reconnect_attempts); +@@ -2799,49 +2818,49 @@ struct rtrs_clt *rtrs_clt_open(struct rtrs_clt_ops *ops, + goto out; + } + for (i = 0; i < paths_num; i++) { +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + +- sess = alloc_sess(clt, &paths[i], nr_cpu_ids, ++ clt_path = alloc_path(clt, &paths[i], nr_cpu_ids, + nr_poll_queues); +- if (IS_ERR(sess)) { +- err = PTR_ERR(sess); +- goto close_all_sess; ++ if (IS_ERR(clt_path)) { ++ err = PTR_ERR(clt_path); ++ goto close_all_path; + } + if (!i) +- sess->for_new_clt = 1; +- list_add_tail_rcu(&sess->s.entry, &clt->paths_list); ++ clt_path->for_new_clt = 1; ++ list_add_tail_rcu(&clt_path->s.entry, &clt->paths_list); + +- err = init_sess(sess); ++ err = init_path(clt_path); + if (err) { +- list_del_rcu(&sess->s.entry); +- rtrs_clt_close_conns(sess, true); +- free_percpu(sess->stats->pcpu_stats); +- kfree(sess->stats); +- free_sess(sess); +- goto close_all_sess; ++ list_del_rcu(&clt_path->s.entry); ++ rtrs_clt_close_conns(clt_path, true); ++ free_percpu(clt_path->stats->pcpu_stats); ++ kfree(clt_path->stats); ++ free_path(clt_path); ++ goto close_all_path; + } + +- err = rtrs_clt_create_sess_files(sess); ++ err = rtrs_clt_create_path_files(clt_path); + if (err) { +- list_del_rcu(&sess->s.entry); +- rtrs_clt_close_conns(sess, true); +- free_percpu(sess->stats->pcpu_stats); +- kfree(sess->stats); +- free_sess(sess); +- goto close_all_sess; ++ list_del_rcu(&clt_path->s.entry); ++ rtrs_clt_close_conns(clt_path, true); ++ free_percpu(clt_path->stats->pcpu_stats); ++ kfree(clt_path->stats); ++ free_path(clt_path); ++ goto close_all_path; + } + } + err = alloc_permits(clt); + if (err) +- goto close_all_sess; ++ goto close_all_path; + + return clt; + +-close_all_sess: +- list_for_each_entry_safe(sess, tmp, &clt->paths_list, s.entry) { +- rtrs_clt_destroy_sess_files(sess, NULL); +- rtrs_clt_close_conns(sess, true); +- kobject_put(&sess->kobj); ++close_all_path: ++ list_for_each_entry_safe(clt_path, tmp, &clt->paths_list, s.entry) { ++ rtrs_clt_destroy_path_files(clt_path, NULL); ++ rtrs_clt_close_conns(clt_path, true); ++ kobject_put(&clt_path->kobj); + } + rtrs_clt_destroy_sysfs_root(clt); + free_clt(clt); +@@ -2852,38 +2871,39 @@ out: + EXPORT_SYMBOL(rtrs_clt_open); + + /** +- * rtrs_clt_close() - Close a session ++ * rtrs_clt_close() - Close a path + * @clt: Session handle. Session is freed upon return. + */ + void rtrs_clt_close(struct rtrs_clt *clt) + { +- struct rtrs_clt_sess *sess, *tmp; ++ struct rtrs_clt_path *clt_path, *tmp; + + /* Firstly forbid sysfs access */ + rtrs_clt_destroy_sysfs_root(clt); + + /* Now it is safe to iterate over all paths without locks */ +- list_for_each_entry_safe(sess, tmp, &clt->paths_list, s.entry) { +- rtrs_clt_close_conns(sess, true); +- rtrs_clt_destroy_sess_files(sess, NULL); +- kobject_put(&sess->kobj); ++ list_for_each_entry_safe(clt_path, tmp, &clt->paths_list, s.entry) { ++ rtrs_clt_close_conns(clt_path, true); ++ rtrs_clt_destroy_path_files(clt_path, NULL); ++ kobject_put(&clt_path->kobj); + } + free_permits(clt); + free_clt(clt); + } + EXPORT_SYMBOL(rtrs_clt_close); + +-int rtrs_clt_reconnect_from_sysfs(struct rtrs_clt_sess *sess) ++int rtrs_clt_reconnect_from_sysfs(struct rtrs_clt_path *clt_path) + { + enum rtrs_clt_state old_state; + int err = -EBUSY; + bool changed; + +- changed = rtrs_clt_change_state_get_old(sess, RTRS_CLT_RECONNECTING, ++ changed = rtrs_clt_change_state_get_old(clt_path, ++ RTRS_CLT_RECONNECTING, + &old_state); + if (changed) { +- sess->reconnect_attempts = 0; +- queue_delayed_work(rtrs_wq, &sess->reconnect_dwork, 0); ++ clt_path->reconnect_attempts = 0; ++ queue_delayed_work(rtrs_wq, &clt_path->reconnect_dwork, 0); + } + if (changed || old_state == RTRS_CLT_RECONNECTING) { + /* +@@ -2891,15 +2911,15 @@ int rtrs_clt_reconnect_from_sysfs(struct rtrs_clt_sess *sess) + * execution, so do the flush if we have queued something + * right now or work is pending. + */ +- flush_delayed_work(&sess->reconnect_dwork); +- err = (READ_ONCE(sess->state) == ++ flush_delayed_work(&clt_path->reconnect_dwork); ++ err = (READ_ONCE(clt_path->state) == + RTRS_CLT_CONNECTED ? 0 : -ENOTCONN); + } + + return err; + } + +-int rtrs_clt_remove_path_from_sysfs(struct rtrs_clt_sess *sess, ++int rtrs_clt_remove_path_from_sysfs(struct rtrs_clt_path *clt_path, + const struct attribute *sysfs_self) + { + enum rtrs_clt_state old_state; +@@ -2915,16 +2935,16 @@ int rtrs_clt_remove_path_from_sysfs(struct rtrs_clt_sess *sess, + * removing the path. + */ + do { +- rtrs_clt_close_conns(sess, true); +- changed = rtrs_clt_change_state_get_old(sess, ++ rtrs_clt_close_conns(clt_path, true); ++ changed = rtrs_clt_change_state_get_old(clt_path, + RTRS_CLT_DEAD, + &old_state); + } while (!changed && old_state != RTRS_CLT_DEAD); + + if (changed) { +- rtrs_clt_remove_path_from_arr(sess); +- rtrs_clt_destroy_sess_files(sess, sysfs_self); +- kobject_put(&sess->kobj); ++ rtrs_clt_remove_path_from_arr(clt_path); ++ rtrs_clt_destroy_path_files(clt_path, sysfs_self); ++ kobject_put(&clt_path->kobj); + } + + return 0; +@@ -2970,7 +2990,7 @@ int rtrs_clt_request(int dir, struct rtrs_clt_req_ops *ops, + struct scatterlist *sg, unsigned int sg_cnt) + { + struct rtrs_clt_io_req *req; +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + + enum dma_data_direction dma_dir; + int err = -ECONNABORTED, i; +@@ -2992,19 +3012,19 @@ int rtrs_clt_request(int dir, struct rtrs_clt_req_ops *ops, + + rcu_read_lock(); + for (path_it_init(&it, clt); +- (sess = it.next_path(&it)) && it.i < it.clt->paths_num; it.i++) { +- if (READ_ONCE(sess->state) != RTRS_CLT_CONNECTED) ++ (clt_path = it.next_path(&it)) && it.i < it.clt->paths_num; it.i++) { ++ if (READ_ONCE(clt_path->state) != RTRS_CLT_CONNECTED) + continue; + +- if (usr_len + hdr_len > sess->max_hdr_size) { +- rtrs_wrn_rl(sess->clt, ++ if (usr_len + hdr_len > clt_path->max_hdr_size) { ++ rtrs_wrn_rl(clt_path->clt, + "%s request failed, user message size is %zu and header length %zu, but max size is %u\n", + dir == READ ? "Read" : "Write", +- usr_len, hdr_len, sess->max_hdr_size); ++ usr_len, hdr_len, clt_path->max_hdr_size); + err = -EMSGSIZE; + break; + } +- req = rtrs_clt_get_req(sess, ops->conf_fn, permit, ops->priv, ++ req = rtrs_clt_get_req(clt_path, ops->conf_fn, permit, ops->priv, + vec, usr_len, sg, sg_cnt, data_len, + dma_dir); + if (dir == READ) +@@ -3030,16 +3050,16 @@ int rtrs_clt_rdma_cq_direct(struct rtrs_clt *clt, unsigned int index) + /* If no path, return -1 for block layer not to try again */ + int cnt = -1; + struct rtrs_con *con; +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + struct path_it it; + + rcu_read_lock(); + for (path_it_init(&it, clt); +- (sess = it.next_path(&it)) && it.i < it.clt->paths_num; it.i++) { +- if (READ_ONCE(sess->state) != RTRS_CLT_CONNECTED) ++ (clt_path = it.next_path(&it)) && it.i < it.clt->paths_num; it.i++) { ++ if (READ_ONCE(clt_path->state) != RTRS_CLT_CONNECTED) + continue; + +- con = sess->s.con[index + 1]; ++ con = clt_path->s.con[index + 1]; + cnt = ib_process_cq_direct(con->cq, -1); + if (cnt) + break; +@@ -3077,12 +3097,12 @@ EXPORT_SYMBOL(rtrs_clt_query); + int rtrs_clt_create_path_from_sysfs(struct rtrs_clt *clt, + struct rtrs_addr *addr) + { +- struct rtrs_clt_sess *sess; ++ struct rtrs_clt_path *clt_path; + int err; + +- sess = alloc_sess(clt, addr, nr_cpu_ids, 0); +- if (IS_ERR(sess)) +- return PTR_ERR(sess); ++ clt_path = alloc_path(clt, addr, nr_cpu_ids, 0); ++ if (IS_ERR(clt_path)) ++ return PTR_ERR(clt_path); + + mutex_lock(&clt->paths_mutex); + if (clt->paths_num == 0) { +@@ -3091,7 +3111,7 @@ int rtrs_clt_create_path_from_sysfs(struct rtrs_clt *clt, + * the addition of the first path is like a new session for + * the storage server + */ +- sess->for_new_clt = 1; ++ clt_path->for_new_clt = 1; + } + + mutex_unlock(&clt->paths_mutex); +@@ -3101,24 +3121,24 @@ int rtrs_clt_create_path_from_sysfs(struct rtrs_clt *clt, + * IO will never grab it. Also it is very important to add + * path before init, since init fires LINK_CONNECTED event. + */ +- rtrs_clt_add_path_to_arr(sess); ++ rtrs_clt_add_path_to_arr(clt_path); + +- err = init_sess(sess); ++ err = init_path(clt_path); + if (err) +- goto close_sess; ++ goto close_path; + +- err = rtrs_clt_create_sess_files(sess); ++ err = rtrs_clt_create_path_files(clt_path); + if (err) +- goto close_sess; ++ goto close_path; + + return 0; + +-close_sess: +- rtrs_clt_remove_path_from_arr(sess); +- rtrs_clt_close_conns(sess, true); +- free_percpu(sess->stats->pcpu_stats); +- kfree(sess->stats); +- free_sess(sess); ++close_path: ++ rtrs_clt_remove_path_from_arr(clt_path); ++ rtrs_clt_close_conns(clt_path, true); ++ free_percpu(clt_path->stats->pcpu_stats); ++ kfree(clt_path->stats); ++ free_path(clt_path); + + return err; + } +diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.h b/drivers/infiniband/ulp/rtrs/rtrs-clt.h +index 9dc819885ec71..7f2a64995fb61 100644 +--- a/drivers/infiniband/ulp/rtrs/rtrs-clt.h ++++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.h +@@ -124,8 +124,8 @@ struct rtrs_rbuf { + u32 rkey; + }; + +-struct rtrs_clt_sess { +- struct rtrs_sess s; ++struct rtrs_clt_path { ++ struct rtrs_path s; + struct rtrs_clt *clt; + wait_queue_head_t state_wq; + enum rtrs_clt_state state; +@@ -156,7 +156,7 @@ struct rtrs_clt_sess { + struct rtrs_clt { + struct list_head paths_list; /* rcu protected list */ + size_t paths_num; +- struct rtrs_clt_sess ++ struct rtrs_clt_path + __rcu * __percpu *pcpu_path; + uuid_t paths_uuid; + int paths_up; +@@ -186,9 +186,9 @@ static inline struct rtrs_clt_con *to_clt_con(struct rtrs_con *c) + return container_of(c, struct rtrs_clt_con, c); + } + +-static inline struct rtrs_clt_sess *to_clt_sess(struct rtrs_sess *s) ++static inline struct rtrs_clt_path *to_clt_path(struct rtrs_path *s) + { +- return container_of(s, struct rtrs_clt_sess, s); ++ return container_of(s, struct rtrs_clt_path, s); + } + + static inline int permit_size(struct rtrs_clt *clt) +@@ -201,16 +201,16 @@ static inline struct rtrs_permit *get_permit(struct rtrs_clt *clt, int idx) + return (struct rtrs_permit *)(clt->permits + permit_size(clt) * idx); + } + +-int rtrs_clt_reconnect_from_sysfs(struct rtrs_clt_sess *sess); +-void rtrs_clt_close_conns(struct rtrs_clt_sess *sess, bool wait); ++int rtrs_clt_reconnect_from_sysfs(struct rtrs_clt_path *path); ++void rtrs_clt_close_conns(struct rtrs_clt_path *clt_path, bool wait); + int rtrs_clt_create_path_from_sysfs(struct rtrs_clt *clt, + struct rtrs_addr *addr); +-int rtrs_clt_remove_path_from_sysfs(struct rtrs_clt_sess *sess, ++int rtrs_clt_remove_path_from_sysfs(struct rtrs_clt_path *path, + const struct attribute *sysfs_self); + + void rtrs_clt_set_max_reconnect_attempts(struct rtrs_clt *clt, int value); + int rtrs_clt_get_max_reconnect_attempts(const struct rtrs_clt *clt); +-void free_sess(struct rtrs_clt_sess *sess); ++void free_path(struct rtrs_clt_path *clt_path); + + /* rtrs-clt-stats.c */ + +@@ -243,8 +243,8 @@ ssize_t rtrs_clt_reset_all_help(struct rtrs_clt_stats *stats, + int rtrs_clt_create_sysfs_root_files(struct rtrs_clt *clt); + void rtrs_clt_destroy_sysfs_root(struct rtrs_clt *clt); + +-int rtrs_clt_create_sess_files(struct rtrs_clt_sess *sess); +-void rtrs_clt_destroy_sess_files(struct rtrs_clt_sess *sess, ++int rtrs_clt_create_path_files(struct rtrs_clt_path *clt_path); ++void rtrs_clt_destroy_path_files(struct rtrs_clt_path *clt_path, + const struct attribute *sysfs_self); + + #endif /* RTRS_CLT_H */ +diff --git a/drivers/infiniband/ulp/rtrs/rtrs-pri.h b/drivers/infiniband/ulp/rtrs/rtrs-pri.h +index d12ddfa507479..b69fa1fe9a707 100644 +--- a/drivers/infiniband/ulp/rtrs/rtrs-pri.h ++++ b/drivers/infiniband/ulp/rtrs/rtrs-pri.h +@@ -23,6 +23,17 @@ + #define RTRS_PROTO_VER_STRING __stringify(RTRS_PROTO_VER_MAJOR) "." \ + __stringify(RTRS_PROTO_VER_MINOR) + ++/* ++ * Max IB immediate data size is 2^28 (MAX_IMM_PAYL_BITS) ++ * and the minimum chunk size is 4096 (2^12). ++ * So the maximum sess_queue_depth is 65536 (2^16) in theory. ++ * But mempool_create, create_qp and ib_post_send fail with ++ * "cannot allocate memory" error if sess_queue_depth is too big. ++ * Therefore the pratical max value of sess_queue_depth is ++ * somewhere between 1 and 65534 and it depends on the system. ++ */ ++#define MAX_SESS_QUEUE_DEPTH 65535 ++ + enum rtrs_imm_const { + MAX_IMM_TYPE_BITS = 4, + MAX_IMM_TYPE_MASK = ((1 << MAX_IMM_TYPE_BITS) - 1), +@@ -46,16 +57,6 @@ enum { + + MAX_PATHS_NUM = 128, + +- /* +- * Max IB immediate data size is 2^28 (MAX_IMM_PAYL_BITS) +- * and the minimum chunk size is 4096 (2^12). +- * So the maximum sess_queue_depth is 65536 (2^16) in theory. +- * But mempool_create, create_qp and ib_post_send fail with +- * "cannot allocate memory" error if sess_queue_depth is too big. +- * Therefore the pratical max value of sess_queue_depth is +- * somewhere between 1 and 65534 and it depends on the system. +- */ +- MAX_SESS_QUEUE_DEPTH = 65535, + MIN_CHUNK_SIZE = 8192, + + RTRS_HB_INTERVAL_MS = 5000, +@@ -90,7 +91,7 @@ struct rtrs_ib_dev { + }; + + struct rtrs_con { +- struct rtrs_sess *sess; ++ struct rtrs_path *path; + struct ib_qp *qp; + struct ib_cq *cq; + struct rdma_cm_id *cm_id; +@@ -100,7 +101,7 @@ struct rtrs_con { + atomic_t sq_wr_avail; + }; + +-struct rtrs_sess { ++struct rtrs_path { + struct list_head entry; + struct sockaddr_storage dst_addr; + struct sockaddr_storage src_addr; +@@ -229,11 +230,11 @@ struct rtrs_msg_conn_rsp { + /** + * struct rtrs_msg_info_req + * @type: @RTRS_MSG_INFO_REQ +- * @sessname: Session name chosen by client ++ * @pathname: Path name chosen by client + */ + struct rtrs_msg_info_req { + __le16 type; +- u8 sessname[NAME_MAX]; ++ u8 pathname[NAME_MAX]; + u8 reserved[15]; + }; + +@@ -313,19 +314,19 @@ int rtrs_iu_post_rdma_write_imm(struct rtrs_con *con, struct rtrs_iu *iu, + + int rtrs_post_recv_empty(struct rtrs_con *con, struct ib_cqe *cqe); + +-int rtrs_cq_qp_create(struct rtrs_sess *sess, struct rtrs_con *con, ++int rtrs_cq_qp_create(struct rtrs_path *path, struct rtrs_con *con, + u32 max_send_sge, int cq_vector, int nr_cqe, + u32 max_send_wr, u32 max_recv_wr, + enum ib_poll_context poll_ctx); + void rtrs_cq_qp_destroy(struct rtrs_con *con); + +-void rtrs_init_hb(struct rtrs_sess *sess, struct ib_cqe *cqe, ++void rtrs_init_hb(struct rtrs_path *path, struct ib_cqe *cqe, + unsigned int interval_ms, unsigned int missed_max, + void (*err_handler)(struct rtrs_con *con), + struct workqueue_struct *wq); +-void rtrs_start_hb(struct rtrs_sess *sess); +-void rtrs_stop_hb(struct rtrs_sess *sess); +-void rtrs_send_hb_ack(struct rtrs_sess *sess); ++void rtrs_start_hb(struct rtrs_path *path); ++void rtrs_stop_hb(struct rtrs_path *path); ++void rtrs_send_hb_ack(struct rtrs_path *path); + + void rtrs_rdma_dev_pd_init(enum ib_pd_flags pd_flags, + struct rtrs_rdma_dev_pd *pool); +diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c b/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c +index 20efd44297fbb..309080184aac7 100644 +--- a/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c ++++ b/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c +@@ -15,10 +15,10 @@ + + static void rtrs_srv_release(struct kobject *kobj) + { +- struct rtrs_srv_sess *sess; ++ struct rtrs_srv_path *srv_path; + +- sess = container_of(kobj, struct rtrs_srv_sess, kobj); +- kfree(sess); ++ srv_path = container_of(kobj, struct rtrs_srv_path, kobj); ++ kfree(srv_path); + } + + static struct kobj_type ktype = { +@@ -36,24 +36,25 @@ static ssize_t rtrs_srv_disconnect_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) + { +- struct rtrs_srv_sess *sess; +- struct rtrs_sess *s; ++ struct rtrs_srv_path *srv_path; ++ struct rtrs_path *s; + char str[MAXHOSTNAMELEN]; + +- sess = container_of(kobj, struct rtrs_srv_sess, kobj); +- s = &sess->s; ++ srv_path = container_of(kobj, struct rtrs_srv_path, kobj); ++ s = &srv_path->s; + if (!sysfs_streq(buf, "1")) { + rtrs_err(s, "%s: invalid value: '%s'\n", + attr->attr.name, buf); + return -EINVAL; + } + +- sockaddr_to_str((struct sockaddr *)&sess->s.dst_addr, str, sizeof(str)); ++ sockaddr_to_str((struct sockaddr *)&srv_path->s.dst_addr, str, ++ sizeof(str)); + + rtrs_info(s, "disconnect for path %s requested\n", str); + /* first remove sysfs itself to avoid deadlock */ +- sysfs_remove_file_self(&sess->kobj, &attr->attr); +- close_sess(sess); ++ sysfs_remove_file_self(&srv_path->kobj, &attr->attr); ++ close_path(srv_path); + + return count; + } +@@ -66,11 +67,11 @@ static ssize_t rtrs_srv_hca_port_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *page) + { +- struct rtrs_srv_sess *sess; ++ struct rtrs_srv_path *srv_path; + struct rtrs_con *usr_con; + +- sess = container_of(kobj, typeof(*sess), kobj); +- usr_con = sess->s.con[0]; ++ srv_path = container_of(kobj, typeof(*srv_path), kobj); ++ usr_con = srv_path->s.con[0]; + + return sysfs_emit(page, "%u\n", usr_con->cm_id->port_num); + } +@@ -82,11 +83,11 @@ static ssize_t rtrs_srv_hca_name_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *page) + { +- struct rtrs_srv_sess *sess; ++ struct rtrs_srv_path *srv_path; + +- sess = container_of(kobj, struct rtrs_srv_sess, kobj); ++ srv_path = container_of(kobj, struct rtrs_srv_path, kobj); + +- return sysfs_emit(page, "%s\n", sess->s.dev->ib_dev->name); ++ return sysfs_emit(page, "%s\n", srv_path->s.dev->ib_dev->name); + } + + static struct kobj_attribute rtrs_srv_hca_name_attr = +@@ -96,11 +97,11 @@ static ssize_t rtrs_srv_src_addr_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *page) + { +- struct rtrs_srv_sess *sess; ++ struct rtrs_srv_path *srv_path; + int cnt; + +- sess = container_of(kobj, struct rtrs_srv_sess, kobj); +- cnt = sockaddr_to_str((struct sockaddr *)&sess->s.dst_addr, ++ srv_path = container_of(kobj, struct rtrs_srv_path, kobj); ++ cnt = sockaddr_to_str((struct sockaddr *)&srv_path->s.dst_addr, + page, PAGE_SIZE); + return cnt + scnprintf(page + cnt, PAGE_SIZE - cnt, "\n"); + } +@@ -112,11 +113,11 @@ static ssize_t rtrs_srv_dst_addr_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *page) + { +- struct rtrs_srv_sess *sess; ++ struct rtrs_srv_path *srv_path; + int len; + +- sess = container_of(kobj, struct rtrs_srv_sess, kobj); +- len = sockaddr_to_str((struct sockaddr *)&sess->s.src_addr, page, ++ srv_path = container_of(kobj, struct rtrs_srv_path, kobj); ++ len = sockaddr_to_str((struct sockaddr *)&srv_path->s.src_addr, page, + PAGE_SIZE); + len += sysfs_emit_at(page, len, "\n"); + return len; +@@ -125,7 +126,7 @@ static ssize_t rtrs_srv_dst_addr_show(struct kobject *kobj, + static struct kobj_attribute rtrs_srv_dst_addr_attr = + __ATTR(dst_addr, 0444, rtrs_srv_dst_addr_show, NULL); + +-static struct attribute *rtrs_srv_sess_attrs[] = { ++static struct attribute *rtrs_srv_path_attrs[] = { + &rtrs_srv_hca_name_attr.attr, + &rtrs_srv_hca_port_attr.attr, + &rtrs_srv_src_addr_attr.attr, +@@ -134,8 +135,8 @@ static struct attribute *rtrs_srv_sess_attrs[] = { + NULL, + }; + +-static const struct attribute_group rtrs_srv_sess_attr_group = { +- .attrs = rtrs_srv_sess_attrs, ++static const struct attribute_group rtrs_srv_path_attr_group = { ++ .attrs = rtrs_srv_path_attrs, + }; + + STAT_ATTR(struct rtrs_srv_stats, rdma, +@@ -151,9 +152,9 @@ static const struct attribute_group rtrs_srv_stats_attr_group = { + .attrs = rtrs_srv_stats_attrs, + }; + +-static int rtrs_srv_create_once_sysfs_root_folders(struct rtrs_srv_sess *sess) ++static int rtrs_srv_create_once_sysfs_root_folders(struct rtrs_srv_path *srv_path) + { +- struct rtrs_srv *srv = sess->srv; ++ struct rtrs_srv *srv = srv_path->srv; + int err = 0; + + mutex_lock(&srv->paths_mutex); +@@ -164,7 +165,7 @@ static int rtrs_srv_create_once_sysfs_root_folders(struct rtrs_srv_sess *sess) + goto unlock; + } + srv->dev.class = rtrs_dev_class; +- err = dev_set_name(&srv->dev, "%s", sess->s.sessname); ++ err = dev_set_name(&srv->dev, "%s", srv_path->s.sessname); + if (err) + goto unlock; + +@@ -196,9 +197,9 @@ unlock: + } + + static void +-rtrs_srv_destroy_once_sysfs_root_folders(struct rtrs_srv_sess *sess) ++rtrs_srv_destroy_once_sysfs_root_folders(struct rtrs_srv_path *srv_path) + { +- struct rtrs_srv *srv = sess->srv; ++ struct rtrs_srv *srv = srv_path->srv; + + mutex_lock(&srv->paths_mutex); + if (!--srv->dev_ref) { +@@ -213,7 +214,7 @@ rtrs_srv_destroy_once_sysfs_root_folders(struct rtrs_srv_sess *sess) + } + } + +-static void rtrs_srv_sess_stats_release(struct kobject *kobj) ++static void rtrs_srv_path_stats_release(struct kobject *kobj) + { + struct rtrs_srv_stats *stats; + +@@ -224,22 +225,22 @@ static void rtrs_srv_sess_stats_release(struct kobject *kobj) + + static struct kobj_type ktype_stats = { + .sysfs_ops = &kobj_sysfs_ops, +- .release = rtrs_srv_sess_stats_release, ++ .release = rtrs_srv_path_stats_release, + }; + +-static int rtrs_srv_create_stats_files(struct rtrs_srv_sess *sess) ++static int rtrs_srv_create_stats_files(struct rtrs_srv_path *srv_path) + { + int err; +- struct rtrs_sess *s = &sess->s; ++ struct rtrs_path *s = &srv_path->s; + +- err = kobject_init_and_add(&sess->stats->kobj_stats, &ktype_stats, +- &sess->kobj, "stats"); ++ err = kobject_init_and_add(&srv_path->stats->kobj_stats, &ktype_stats, ++ &srv_path->kobj, "stats"); + if (err) { + rtrs_err(s, "kobject_init_and_add(): %d\n", err); +- kobject_put(&sess->stats->kobj_stats); ++ kobject_put(&srv_path->stats->kobj_stats); + return err; + } +- err = sysfs_create_group(&sess->stats->kobj_stats, ++ err = sysfs_create_group(&srv_path->stats->kobj_stats, + &rtrs_srv_stats_attr_group); + if (err) { + rtrs_err(s, "sysfs_create_group(): %d\n", err); +@@ -249,64 +250,64 @@ static int rtrs_srv_create_stats_files(struct rtrs_srv_sess *sess) + return 0; + + err: +- kobject_del(&sess->stats->kobj_stats); +- kobject_put(&sess->stats->kobj_stats); ++ kobject_del(&srv_path->stats->kobj_stats); ++ kobject_put(&srv_path->stats->kobj_stats); + + return err; + } + +-int rtrs_srv_create_sess_files(struct rtrs_srv_sess *sess) ++int rtrs_srv_create_path_files(struct rtrs_srv_path *srv_path) + { +- struct rtrs_srv *srv = sess->srv; +- struct rtrs_sess *s = &sess->s; ++ struct rtrs_srv *srv = srv_path->srv; ++ struct rtrs_path *s = &srv_path->s; + char str[NAME_MAX]; + int err; + struct rtrs_addr path = { +- .src = &sess->s.dst_addr, +- .dst = &sess->s.src_addr, ++ .src = &srv_path->s.dst_addr, ++ .dst = &srv_path->s.src_addr, + }; + + rtrs_addr_to_str(&path, str, sizeof(str)); +- err = rtrs_srv_create_once_sysfs_root_folders(sess); ++ err = rtrs_srv_create_once_sysfs_root_folders(srv_path); + if (err) + return err; + +- err = kobject_init_and_add(&sess->kobj, &ktype, srv->kobj_paths, ++ err = kobject_init_and_add(&srv_path->kobj, &ktype, srv->kobj_paths, + "%s", str); + if (err) { + rtrs_err(s, "kobject_init_and_add(): %d\n", err); + goto destroy_root; + } +- err = sysfs_create_group(&sess->kobj, &rtrs_srv_sess_attr_group); ++ err = sysfs_create_group(&srv_path->kobj, &rtrs_srv_path_attr_group); + if (err) { + rtrs_err(s, "sysfs_create_group(): %d\n", err); + goto put_kobj; + } +- err = rtrs_srv_create_stats_files(sess); ++ err = rtrs_srv_create_stats_files(srv_path); + if (err) + goto remove_group; + + return 0; + + remove_group: +- sysfs_remove_group(&sess->kobj, &rtrs_srv_sess_attr_group); ++ sysfs_remove_group(&srv_path->kobj, &rtrs_srv_path_attr_group); + put_kobj: +- kobject_del(&sess->kobj); ++ kobject_del(&srv_path->kobj); + destroy_root: +- kobject_put(&sess->kobj); +- rtrs_srv_destroy_once_sysfs_root_folders(sess); ++ kobject_put(&srv_path->kobj); ++ rtrs_srv_destroy_once_sysfs_root_folders(srv_path); + + return err; + } + +-void rtrs_srv_destroy_sess_files(struct rtrs_srv_sess *sess) ++void rtrs_srv_destroy_path_files(struct rtrs_srv_path *srv_path) + { +- if (sess->kobj.state_in_sysfs) { +- kobject_del(&sess->stats->kobj_stats); +- kobject_put(&sess->stats->kobj_stats); +- sysfs_remove_group(&sess->kobj, &rtrs_srv_sess_attr_group); +- kobject_put(&sess->kobj); ++ if (srv_path->kobj.state_in_sysfs) { ++ kobject_del(&srv_path->stats->kobj_stats); ++ kobject_put(&srv_path->stats->kobj_stats); ++ sysfs_remove_group(&srv_path->kobj, &rtrs_srv_path_attr_group); ++ kobject_put(&srv_path->kobj); + +- rtrs_srv_destroy_once_sysfs_root_folders(sess); ++ rtrs_srv_destroy_once_sysfs_root_folders(srv_path); + } + } +diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c +index 716ef7b235587..1ca31b919e987 100644 +--- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c ++++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c +@@ -62,19 +62,19 @@ static inline struct rtrs_srv_con *to_srv_con(struct rtrs_con *c) + return container_of(c, struct rtrs_srv_con, c); + } + +-static inline struct rtrs_srv_sess *to_srv_sess(struct rtrs_sess *s) ++static inline struct rtrs_srv_path *to_srv_path(struct rtrs_path *s) + { +- return container_of(s, struct rtrs_srv_sess, s); ++ return container_of(s, struct rtrs_srv_path, s); + } + +-static bool rtrs_srv_change_state(struct rtrs_srv_sess *sess, ++static bool rtrs_srv_change_state(struct rtrs_srv_path *srv_path, + enum rtrs_srv_state new_state) + { + enum rtrs_srv_state old_state; + bool changed = false; + +- spin_lock_irq(&sess->state_lock); +- old_state = sess->state; ++ spin_lock_irq(&srv_path->state_lock); ++ old_state = srv_path->state; + switch (new_state) { + case RTRS_SRV_CONNECTED: + if (old_state == RTRS_SRV_CONNECTING) +@@ -93,8 +93,8 @@ static bool rtrs_srv_change_state(struct rtrs_srv_sess *sess, + break; + } + if (changed) +- sess->state = new_state; +- spin_unlock_irq(&sess->state_lock); ++ srv_path->state = new_state; ++ spin_unlock_irq(&srv_path->state_lock); + + return changed; + } +@@ -106,16 +106,16 @@ static void free_id(struct rtrs_srv_op *id) + kfree(id); + } + +-static void rtrs_srv_free_ops_ids(struct rtrs_srv_sess *sess) ++static void rtrs_srv_free_ops_ids(struct rtrs_srv_path *srv_path) + { +- struct rtrs_srv *srv = sess->srv; ++ struct rtrs_srv *srv = srv_path->srv; + int i; + +- if (sess->ops_ids) { ++ if (srv_path->ops_ids) { + for (i = 0; i < srv->queue_depth; i++) +- free_id(sess->ops_ids[i]); +- kfree(sess->ops_ids); +- sess->ops_ids = NULL; ++ free_id(srv_path->ops_ids[i]); ++ kfree(srv_path->ops_ids); ++ srv_path->ops_ids = NULL; + } + } + +@@ -127,21 +127,24 @@ static struct ib_cqe io_comp_cqe = { + + static inline void rtrs_srv_inflight_ref_release(struct percpu_ref *ref) + { +- struct rtrs_srv_sess *sess = container_of(ref, struct rtrs_srv_sess, ids_inflight_ref); ++ struct rtrs_srv_path *srv_path = container_of(ref, ++ struct rtrs_srv_path, ++ ids_inflight_ref); + +- percpu_ref_exit(&sess->ids_inflight_ref); +- complete(&sess->complete_done); ++ percpu_ref_exit(&srv_path->ids_inflight_ref); ++ complete(&srv_path->complete_done); + } + +-static int rtrs_srv_alloc_ops_ids(struct rtrs_srv_sess *sess) ++static int rtrs_srv_alloc_ops_ids(struct rtrs_srv_path *srv_path) + { +- struct rtrs_srv *srv = sess->srv; ++ struct rtrs_srv *srv = srv_path->srv; + struct rtrs_srv_op *id; + int i, ret; + +- sess->ops_ids = kcalloc(srv->queue_depth, sizeof(*sess->ops_ids), +- GFP_KERNEL); +- if (!sess->ops_ids) ++ srv_path->ops_ids = kcalloc(srv->queue_depth, ++ sizeof(*srv_path->ops_ids), ++ GFP_KERNEL); ++ if (!srv_path->ops_ids) + goto err; + + for (i = 0; i < srv->queue_depth; ++i) { +@@ -149,44 +152,44 @@ static int rtrs_srv_alloc_ops_ids(struct rtrs_srv_sess *sess) + if (!id) + goto err; + +- sess->ops_ids[i] = id; ++ srv_path->ops_ids[i] = id; + } + +- ret = percpu_ref_init(&sess->ids_inflight_ref, ++ ret = percpu_ref_init(&srv_path->ids_inflight_ref, + rtrs_srv_inflight_ref_release, 0, GFP_KERNEL); + if (ret) { + pr_err("Percpu reference init failed\n"); + goto err; + } +- init_completion(&sess->complete_done); ++ init_completion(&srv_path->complete_done); + + return 0; + + err: +- rtrs_srv_free_ops_ids(sess); ++ rtrs_srv_free_ops_ids(srv_path); + return -ENOMEM; + } + +-static inline void rtrs_srv_get_ops_ids(struct rtrs_srv_sess *sess) ++static inline void rtrs_srv_get_ops_ids(struct rtrs_srv_path *srv_path) + { +- percpu_ref_get(&sess->ids_inflight_ref); ++ percpu_ref_get(&srv_path->ids_inflight_ref); + } + +-static inline void rtrs_srv_put_ops_ids(struct rtrs_srv_sess *sess) ++static inline void rtrs_srv_put_ops_ids(struct rtrs_srv_path *srv_path) + { +- percpu_ref_put(&sess->ids_inflight_ref); ++ percpu_ref_put(&srv_path->ids_inflight_ref); + } + + static void rtrs_srv_reg_mr_done(struct ib_cq *cq, struct ib_wc *wc) + { + struct rtrs_srv_con *con = to_srv_con(wc->qp->qp_context); +- struct rtrs_sess *s = con->c.sess; +- struct rtrs_srv_sess *sess = to_srv_sess(s); ++ struct rtrs_path *s = con->c.path; ++ struct rtrs_srv_path *srv_path = to_srv_path(s); + + if (wc->status != IB_WC_SUCCESS) { + rtrs_err(s, "REG MR failed: %s\n", + ib_wc_status_msg(wc->status)); +- close_sess(sess); ++ close_path(srv_path); + return; + } + } +@@ -197,9 +200,9 @@ static struct ib_cqe local_reg_cqe = { + + static int rdma_write_sg(struct rtrs_srv_op *id) + { +- struct rtrs_sess *s = id->con->c.sess; +- struct rtrs_srv_sess *sess = to_srv_sess(s); +- dma_addr_t dma_addr = sess->dma_addr[id->msg_id]; ++ struct rtrs_path *s = id->con->c.path; ++ struct rtrs_srv_path *srv_path = to_srv_path(s); ++ dma_addr_t dma_addr = srv_path->dma_addr[id->msg_id]; + struct rtrs_srv_mr *srv_mr; + struct ib_send_wr inv_wr; + struct ib_rdma_wr imm_wr; +@@ -233,7 +236,7 @@ static int rdma_write_sg(struct rtrs_srv_op *id) + return -EINVAL; + } + +- plist->lkey = sess->s.dev->ib_pd->local_dma_lkey; ++ plist->lkey = srv_path->s.dev->ib_pd->local_dma_lkey; + offset += plist->length; + + wr->wr.sg_list = plist; +@@ -284,7 +287,7 @@ static int rdma_write_sg(struct rtrs_srv_op *id) + if (always_invalidate) { + struct rtrs_msg_rkey_rsp *msg; + +- srv_mr = &sess->mrs[id->msg_id]; ++ srv_mr = &srv_path->mrs[id->msg_id]; + rwr.wr.opcode = IB_WR_REG_MR; + rwr.wr.wr_cqe = &local_reg_cqe; + rwr.wr.num_sge = 0; +@@ -300,11 +303,11 @@ static int rdma_write_sg(struct rtrs_srv_op *id) + + list.addr = srv_mr->iu->dma_addr; + list.length = sizeof(*msg); +- list.lkey = sess->s.dev->ib_pd->local_dma_lkey; ++ list.lkey = srv_path->s.dev->ib_pd->local_dma_lkey; + imm_wr.wr.sg_list = &list; + imm_wr.wr.num_sge = 1; + imm_wr.wr.opcode = IB_WR_SEND_WITH_IMM; +- ib_dma_sync_single_for_device(sess->s.dev->ib_dev, ++ ib_dma_sync_single_for_device(srv_path->s.dev->ib_dev, + srv_mr->iu->dma_addr, + srv_mr->iu->size, DMA_TO_DEVICE); + } else { +@@ -317,7 +320,7 @@ static int rdma_write_sg(struct rtrs_srv_op *id) + 0, need_inval)); + + imm_wr.wr.wr_cqe = &io_comp_cqe; +- ib_dma_sync_single_for_device(sess->s.dev->ib_dev, dma_addr, ++ ib_dma_sync_single_for_device(srv_path->s.dev->ib_dev, dma_addr, + offset, DMA_BIDIRECTIONAL); + + err = ib_post_send(id->con->c.qp, &id->tx_wr.wr, NULL); +@@ -341,8 +344,8 @@ static int rdma_write_sg(struct rtrs_srv_op *id) + static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id, + int errno) + { +- struct rtrs_sess *s = con->c.sess; +- struct rtrs_srv_sess *sess = to_srv_sess(s); ++ struct rtrs_path *s = con->c.path; ++ struct rtrs_srv_path *srv_path = to_srv_path(s); + struct ib_send_wr inv_wr, *wr = NULL; + struct ib_rdma_wr imm_wr; + struct ib_reg_wr rwr; +@@ -402,7 +405,7 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id, + struct ib_sge list; + struct rtrs_msg_rkey_rsp *msg; + +- srv_mr = &sess->mrs[id->msg_id]; ++ srv_mr = &srv_path->mrs[id->msg_id]; + rwr.wr.next = &imm_wr.wr; + rwr.wr.opcode = IB_WR_REG_MR; + rwr.wr.wr_cqe = &local_reg_cqe; +@@ -419,11 +422,11 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id, + + list.addr = srv_mr->iu->dma_addr; + list.length = sizeof(*msg); +- list.lkey = sess->s.dev->ib_pd->local_dma_lkey; ++ list.lkey = srv_path->s.dev->ib_pd->local_dma_lkey; + imm_wr.wr.sg_list = &list; + imm_wr.wr.num_sge = 1; + imm_wr.wr.opcode = IB_WR_SEND_WITH_IMM; +- ib_dma_sync_single_for_device(sess->s.dev->ib_dev, ++ ib_dma_sync_single_for_device(srv_path->s.dev->ib_dev, + srv_mr->iu->dma_addr, + srv_mr->iu->size, DMA_TO_DEVICE); + } else { +@@ -444,11 +447,11 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id, + return err; + } + +-void close_sess(struct rtrs_srv_sess *sess) ++void close_path(struct rtrs_srv_path *srv_path) + { +- if (rtrs_srv_change_state(sess, RTRS_SRV_CLOSING)) +- queue_work(rtrs_wq, &sess->close_work); +- WARN_ON(sess->state != RTRS_SRV_CLOSING); ++ if (rtrs_srv_change_state(srv_path, RTRS_SRV_CLOSING)) ++ queue_work(rtrs_wq, &srv_path->close_work); ++ WARN_ON(srv_path->state != RTRS_SRV_CLOSING); + } + + static inline const char *rtrs_srv_state_str(enum rtrs_srv_state state) +@@ -480,35 +483,35 @@ static inline const char *rtrs_srv_state_str(enum rtrs_srv_state state) + */ + bool rtrs_srv_resp_rdma(struct rtrs_srv_op *id, int status) + { +- struct rtrs_srv_sess *sess; ++ struct rtrs_srv_path *srv_path; + struct rtrs_srv_con *con; +- struct rtrs_sess *s; ++ struct rtrs_path *s; + int err; + + if (WARN_ON(!id)) + return true; + + con = id->con; +- s = con->c.sess; +- sess = to_srv_sess(s); ++ s = con->c.path; ++ srv_path = to_srv_path(s); + + id->status = status; + +- if (sess->state != RTRS_SRV_CONNECTED) { ++ if (srv_path->state != RTRS_SRV_CONNECTED) { + rtrs_err_rl(s, +- "Sending I/O response failed, session %s is disconnected, sess state %s\n", +- kobject_name(&sess->kobj), +- rtrs_srv_state_str(sess->state)); ++ "Sending I/O response failed, server path %s is disconnected, path state %s\n", ++ kobject_name(&srv_path->kobj), ++ rtrs_srv_state_str(srv_path->state)); + goto out; + } + if (always_invalidate) { +- struct rtrs_srv_mr *mr = &sess->mrs[id->msg_id]; ++ struct rtrs_srv_mr *mr = &srv_path->mrs[id->msg_id]; + + ib_update_fast_reg_key(mr->mr, ib_inc_rkey(mr->mr->rkey)); + } + if (atomic_sub_return(1, &con->c.sq_wr_avail) < 0) { +- rtrs_err(s, "IB send queue full: sess=%s cid=%d\n", +- kobject_name(&sess->kobj), ++ rtrs_err(s, "IB send queue full: srv_path=%s cid=%d\n", ++ kobject_name(&srv_path->kobj), + con->c.cid); + atomic_add(1, &con->c.sq_wr_avail); + spin_lock(&con->rsp_wr_wait_lock); +@@ -523,12 +526,12 @@ bool rtrs_srv_resp_rdma(struct rtrs_srv_op *id, int status) + err = rdma_write_sg(id); + + if (err) { +- rtrs_err_rl(s, "IO response failed: %d: sess=%s\n", err, +- kobject_name(&sess->kobj)); +- close_sess(sess); ++ rtrs_err_rl(s, "IO response failed: %d: srv_path=%s\n", err, ++ kobject_name(&srv_path->kobj)); ++ close_path(srv_path); + } + out: +- rtrs_srv_put_ops_ids(sess); ++ rtrs_srv_put_ops_ids(srv_path); + return true; + } + EXPORT_SYMBOL(rtrs_srv_resp_rdma); +@@ -544,27 +547,27 @@ void rtrs_srv_set_sess_priv(struct rtrs_srv *srv, void *priv) + } + EXPORT_SYMBOL(rtrs_srv_set_sess_priv); + +-static void unmap_cont_bufs(struct rtrs_srv_sess *sess) ++static void unmap_cont_bufs(struct rtrs_srv_path *srv_path) + { + int i; + +- for (i = 0; i < sess->mrs_num; i++) { ++ for (i = 0; i < srv_path->mrs_num; i++) { + struct rtrs_srv_mr *srv_mr; + +- srv_mr = &sess->mrs[i]; +- rtrs_iu_free(srv_mr->iu, sess->s.dev->ib_dev, 1); ++ srv_mr = &srv_path->mrs[i]; ++ rtrs_iu_free(srv_mr->iu, srv_path->s.dev->ib_dev, 1); + ib_dereg_mr(srv_mr->mr); +- ib_dma_unmap_sg(sess->s.dev->ib_dev, srv_mr->sgt.sgl, ++ ib_dma_unmap_sg(srv_path->s.dev->ib_dev, srv_mr->sgt.sgl, + srv_mr->sgt.nents, DMA_BIDIRECTIONAL); + sg_free_table(&srv_mr->sgt); + } +- kfree(sess->mrs); ++ kfree(srv_path->mrs); + } + +-static int map_cont_bufs(struct rtrs_srv_sess *sess) ++static int map_cont_bufs(struct rtrs_srv_path *srv_path) + { +- struct rtrs_srv *srv = sess->srv; +- struct rtrs_sess *ss = &sess->s; ++ struct rtrs_srv *srv = srv_path->srv; ++ struct rtrs_path *ss = &srv_path->s; + int i, mri, err, mrs_num; + unsigned int chunk_bits; + int chunks_per_mr = 1; +@@ -581,19 +584,19 @@ static int map_cont_bufs(struct rtrs_srv_sess *sess) + mrs_num = srv->queue_depth; + } else { + chunks_per_mr = +- sess->s.dev->ib_dev->attrs.max_fast_reg_page_list_len; ++ srv_path->s.dev->ib_dev->attrs.max_fast_reg_page_list_len; + mrs_num = DIV_ROUND_UP(srv->queue_depth, chunks_per_mr); + chunks_per_mr = DIV_ROUND_UP(srv->queue_depth, mrs_num); + } + +- sess->mrs = kcalloc(mrs_num, sizeof(*sess->mrs), GFP_KERNEL); +- if (!sess->mrs) ++ srv_path->mrs = kcalloc(mrs_num, sizeof(*srv_path->mrs), GFP_KERNEL); ++ if (!srv_path->mrs) + return -ENOMEM; + +- sess->mrs_num = mrs_num; ++ srv_path->mrs_num = mrs_num; + + for (mri = 0; mri < mrs_num; mri++) { +- struct rtrs_srv_mr *srv_mr = &sess->mrs[mri]; ++ struct rtrs_srv_mr *srv_mr = &srv_path->mrs[mri]; + struct sg_table *sgt = &srv_mr->sgt; + struct scatterlist *s; + struct ib_mr *mr; +@@ -612,13 +615,13 @@ static int map_cont_bufs(struct rtrs_srv_sess *sess) + sg_set_page(s, srv->chunks[chunks + i], + max_chunk_size, 0); + +- nr = ib_dma_map_sg(sess->s.dev->ib_dev, sgt->sgl, ++ nr = ib_dma_map_sg(srv_path->s.dev->ib_dev, sgt->sgl, + sgt->nents, DMA_BIDIRECTIONAL); + if (nr < sgt->nents) { + err = nr < 0 ? nr : -EINVAL; + goto free_sg; + } +- mr = ib_alloc_mr(sess->s.dev->ib_pd, IB_MR_TYPE_MEM_REG, ++ mr = ib_alloc_mr(srv_path->s.dev->ib_pd, IB_MR_TYPE_MEM_REG, + sgt->nents); + if (IS_ERR(mr)) { + err = PTR_ERR(mr); +@@ -634,7 +637,7 @@ static int map_cont_bufs(struct rtrs_srv_sess *sess) + if (always_invalidate) { + srv_mr->iu = rtrs_iu_alloc(1, + sizeof(struct rtrs_msg_rkey_rsp), +- GFP_KERNEL, sess->s.dev->ib_dev, ++ GFP_KERNEL, srv_path->s.dev->ib_dev, + DMA_TO_DEVICE, rtrs_srv_rdma_done); + if (!srv_mr->iu) { + err = -ENOMEM; +@@ -644,7 +647,7 @@ static int map_cont_bufs(struct rtrs_srv_sess *sess) + } + /* Eventually dma addr for each chunk can be cached */ + for_each_sg(sgt->sgl, s, sgt->orig_nents, i) +- sess->dma_addr[chunks + i] = sg_dma_address(s); ++ srv_path->dma_addr[chunks + i] = sg_dma_address(s); + + ib_update_fast_reg_key(mr, ib_inc_rkey(mr->rkey)); + srv_mr->mr = mr; +@@ -652,75 +655,75 @@ static int map_cont_bufs(struct rtrs_srv_sess *sess) + continue; + err: + while (mri--) { +- srv_mr = &sess->mrs[mri]; ++ srv_mr = &srv_path->mrs[mri]; + sgt = &srv_mr->sgt; + mr = srv_mr->mr; +- rtrs_iu_free(srv_mr->iu, sess->s.dev->ib_dev, 1); ++ rtrs_iu_free(srv_mr->iu, srv_path->s.dev->ib_dev, 1); + dereg_mr: + ib_dereg_mr(mr); + unmap_sg: +- ib_dma_unmap_sg(sess->s.dev->ib_dev, sgt->sgl, ++ ib_dma_unmap_sg(srv_path->s.dev->ib_dev, sgt->sgl, + sgt->nents, DMA_BIDIRECTIONAL); + free_sg: + sg_free_table(sgt); + } +- kfree(sess->mrs); ++ kfree(srv_path->mrs); + + return err; + } + + chunk_bits = ilog2(srv->queue_depth - 1) + 1; +- sess->mem_bits = (MAX_IMM_PAYL_BITS - chunk_bits); ++ srv_path->mem_bits = (MAX_IMM_PAYL_BITS - chunk_bits); + + return 0; + } + + static void rtrs_srv_hb_err_handler(struct rtrs_con *c) + { +- close_sess(to_srv_sess(c->sess)); ++ close_path(to_srv_path(c->path)); + } + +-static void rtrs_srv_init_hb(struct rtrs_srv_sess *sess) ++static void rtrs_srv_init_hb(struct rtrs_srv_path *srv_path) + { +- rtrs_init_hb(&sess->s, &io_comp_cqe, ++ rtrs_init_hb(&srv_path->s, &io_comp_cqe, + RTRS_HB_INTERVAL_MS, + RTRS_HB_MISSED_MAX, + rtrs_srv_hb_err_handler, + rtrs_wq); + } + +-static void rtrs_srv_start_hb(struct rtrs_srv_sess *sess) ++static void rtrs_srv_start_hb(struct rtrs_srv_path *srv_path) + { +- rtrs_start_hb(&sess->s); ++ rtrs_start_hb(&srv_path->s); + } + +-static void rtrs_srv_stop_hb(struct rtrs_srv_sess *sess) ++static void rtrs_srv_stop_hb(struct rtrs_srv_path *srv_path) + { +- rtrs_stop_hb(&sess->s); ++ rtrs_stop_hb(&srv_path->s); + } + + static void rtrs_srv_info_rsp_done(struct ib_cq *cq, struct ib_wc *wc) + { + struct rtrs_srv_con *con = to_srv_con(wc->qp->qp_context); +- struct rtrs_sess *s = con->c.sess; +- struct rtrs_srv_sess *sess = to_srv_sess(s); ++ struct rtrs_path *s = con->c.path; ++ struct rtrs_srv_path *srv_path = to_srv_path(s); + struct rtrs_iu *iu; + + iu = container_of(wc->wr_cqe, struct rtrs_iu, cqe); +- rtrs_iu_free(iu, sess->s.dev->ib_dev, 1); ++ rtrs_iu_free(iu, srv_path->s.dev->ib_dev, 1); + + if (wc->status != IB_WC_SUCCESS) { + rtrs_err(s, "Sess info response send failed: %s\n", + ib_wc_status_msg(wc->status)); +- close_sess(sess); ++ close_path(srv_path); + return; + } + WARN_ON(wc->opcode != IB_WC_SEND); + } + +-static void rtrs_srv_sess_up(struct rtrs_srv_sess *sess) ++static void rtrs_srv_path_up(struct rtrs_srv_path *srv_path) + { +- struct rtrs_srv *srv = sess->srv; ++ struct rtrs_srv *srv = srv_path->srv; + struct rtrs_srv_ctx *ctx = srv->ctx; + int up; + +@@ -731,18 +734,18 @@ static void rtrs_srv_sess_up(struct rtrs_srv_sess *sess) + mutex_unlock(&srv->paths_ev_mutex); + + /* Mark session as established */ +- sess->established = true; ++ srv_path->established = true; + } + +-static void rtrs_srv_sess_down(struct rtrs_srv_sess *sess) ++static void rtrs_srv_path_down(struct rtrs_srv_path *srv_path) + { +- struct rtrs_srv *srv = sess->srv; ++ struct rtrs_srv *srv = srv_path->srv; + struct rtrs_srv_ctx *ctx = srv->ctx; + +- if (!sess->established) ++ if (!srv_path->established) + return; + +- sess->established = false; ++ srv_path->established = false; + mutex_lock(&srv->paths_ev_mutex); + WARN_ON(!srv->paths_up); + if (--srv->paths_up == 0) +@@ -750,11 +753,11 @@ static void rtrs_srv_sess_down(struct rtrs_srv_sess *sess) + mutex_unlock(&srv->paths_ev_mutex); + } + +-static bool exist_sessname(struct rtrs_srv_ctx *ctx, +- const char *sessname, const uuid_t *path_uuid) ++static bool exist_pathname(struct rtrs_srv_ctx *ctx, ++ const char *pathname, const uuid_t *path_uuid) + { + struct rtrs_srv *srv; +- struct rtrs_srv_sess *sess; ++ struct rtrs_srv_path *srv_path; + bool found = false; + + mutex_lock(&ctx->srv_mutex); +@@ -767,9 +770,9 @@ static bool exist_sessname(struct rtrs_srv_ctx *ctx, + continue; + } + +- list_for_each_entry(sess, &srv->paths_list, s.entry) { +- if (strlen(sess->s.sessname) == strlen(sessname) && +- !strcmp(sess->s.sessname, sessname)) { ++ list_for_each_entry(srv_path, &srv->paths_list, s.entry) { ++ if (strlen(srv_path->s.sessname) == strlen(pathname) && ++ !strcmp(srv_path->s.sessname, pathname)) { + found = true; + break; + } +@@ -782,14 +785,14 @@ static bool exist_sessname(struct rtrs_srv_ctx *ctx, + return found; + } + +-static int post_recv_sess(struct rtrs_srv_sess *sess); ++static int post_recv_path(struct rtrs_srv_path *srv_path); + static int rtrs_rdma_do_reject(struct rdma_cm_id *cm_id, int errno); + + static int process_info_req(struct rtrs_srv_con *con, + struct rtrs_msg_info_req *msg) + { +- struct rtrs_sess *s = con->c.sess; +- struct rtrs_srv_sess *sess = to_srv_sess(s); ++ struct rtrs_path *s = con->c.path; ++ struct rtrs_srv_path *srv_path = to_srv_path(s); + struct ib_send_wr *reg_wr = NULL; + struct rtrs_msg_info_rsp *rsp; + struct rtrs_iu *tx_iu; +@@ -797,26 +800,32 @@ static int process_info_req(struct rtrs_srv_con *con, + int mri, err; + size_t tx_sz; + +- err = post_recv_sess(sess); ++ err = post_recv_path(srv_path); + if (err) { +- rtrs_err(s, "post_recv_sess(), err: %d\n", err); ++ rtrs_err(s, "post_recv_path(), err: %d\n", err); + return err; + } + +- if (exist_sessname(sess->srv->ctx, +- msg->sessname, &sess->srv->paths_uuid)) { +- rtrs_err(s, "sessname is duplicated: %s\n", msg->sessname); ++ if (strchr(msg->pathname, '/') || strchr(msg->pathname, '.')) { ++ rtrs_err(s, "pathname cannot contain / and .\n"); ++ return -EINVAL; ++ } ++ ++ if (exist_pathname(srv_path->srv->ctx, ++ msg->pathname, &srv_path->srv->paths_uuid)) { ++ rtrs_err(s, "pathname is duplicated: %s\n", msg->pathname); + return -EPERM; + } +- strscpy(sess->s.sessname, msg->sessname, sizeof(sess->s.sessname)); ++ strscpy(srv_path->s.sessname, msg->pathname, ++ sizeof(srv_path->s.sessname)); + +- rwr = kcalloc(sess->mrs_num, sizeof(*rwr), GFP_KERNEL); ++ rwr = kcalloc(srv_path->mrs_num, sizeof(*rwr), GFP_KERNEL); + if (!rwr) + return -ENOMEM; + + tx_sz = sizeof(*rsp); +- tx_sz += sizeof(rsp->desc[0]) * sess->mrs_num; +- tx_iu = rtrs_iu_alloc(1, tx_sz, GFP_KERNEL, sess->s.dev->ib_dev, ++ tx_sz += sizeof(rsp->desc[0]) * srv_path->mrs_num; ++ tx_iu = rtrs_iu_alloc(1, tx_sz, GFP_KERNEL, srv_path->s.dev->ib_dev, + DMA_TO_DEVICE, rtrs_srv_info_rsp_done); + if (!tx_iu) { + err = -ENOMEM; +@@ -825,10 +834,10 @@ static int process_info_req(struct rtrs_srv_con *con, + + rsp = tx_iu->buf; + rsp->type = cpu_to_le16(RTRS_MSG_INFO_RSP); +- rsp->sg_cnt = cpu_to_le16(sess->mrs_num); ++ rsp->sg_cnt = cpu_to_le16(srv_path->mrs_num); + +- for (mri = 0; mri < sess->mrs_num; mri++) { +- struct ib_mr *mr = sess->mrs[mri].mr; ++ for (mri = 0; mri < srv_path->mrs_num; mri++) { ++ struct ib_mr *mr = srv_path->mrs[mri].mr; + + rsp->desc[mri].addr = cpu_to_le64(mr->iova); + rsp->desc[mri].key = cpu_to_le32(mr->rkey); +@@ -849,13 +858,13 @@ static int process_info_req(struct rtrs_srv_con *con, + reg_wr = &rwr[mri].wr; + } + +- err = rtrs_srv_create_sess_files(sess); ++ err = rtrs_srv_create_path_files(srv_path); + if (err) + goto iu_free; +- kobject_get(&sess->kobj); +- get_device(&sess->srv->dev); +- rtrs_srv_change_state(sess, RTRS_SRV_CONNECTED); +- rtrs_srv_start_hb(sess); ++ kobject_get(&srv_path->kobj); ++ get_device(&srv_path->srv->dev); ++ rtrs_srv_change_state(srv_path, RTRS_SRV_CONNECTED); ++ rtrs_srv_start_hb(srv_path); + + /* + * We do not account number of established connections at the current +@@ -863,9 +872,10 @@ static int process_info_req(struct rtrs_srv_con *con, + * all connections are successfully established. Thus, simply notify + * listener with a proper event if we are the first path. + */ +- rtrs_srv_sess_up(sess); ++ rtrs_srv_path_up(srv_path); + +- ib_dma_sync_single_for_device(sess->s.dev->ib_dev, tx_iu->dma_addr, ++ ib_dma_sync_single_for_device(srv_path->s.dev->ib_dev, ++ tx_iu->dma_addr, + tx_iu->size, DMA_TO_DEVICE); + + /* Send info response */ +@@ -873,7 +883,7 @@ static int process_info_req(struct rtrs_srv_con *con, + if (err) { + rtrs_err(s, "rtrs_iu_post_send(), err: %d\n", err); + iu_free: +- rtrs_iu_free(tx_iu, sess->s.dev->ib_dev, 1); ++ rtrs_iu_free(tx_iu, srv_path->s.dev->ib_dev, 1); + } + rwr_free: + kfree(rwr); +@@ -884,8 +894,8 @@ rwr_free: + static void rtrs_srv_info_req_done(struct ib_cq *cq, struct ib_wc *wc) + { + struct rtrs_srv_con *con = to_srv_con(wc->qp->qp_context); +- struct rtrs_sess *s = con->c.sess; +- struct rtrs_srv_sess *sess = to_srv_sess(s); ++ struct rtrs_path *s = con->c.path; ++ struct rtrs_srv_path *srv_path = to_srv_path(s); + struct rtrs_msg_info_req *msg; + struct rtrs_iu *iu; + int err; +@@ -905,7 +915,7 @@ static void rtrs_srv_info_req_done(struct ib_cq *cq, struct ib_wc *wc) + wc->byte_len); + goto close; + } +- ib_dma_sync_single_for_cpu(sess->s.dev->ib_dev, iu->dma_addr, ++ ib_dma_sync_single_for_cpu(srv_path->s.dev->ib_dev, iu->dma_addr, + iu->size, DMA_FROM_DEVICE); + msg = iu->buf; + if (le16_to_cpu(msg->type) != RTRS_MSG_INFO_REQ) { +@@ -918,22 +928,22 @@ static void rtrs_srv_info_req_done(struct ib_cq *cq, struct ib_wc *wc) + goto close; + + out: +- rtrs_iu_free(iu, sess->s.dev->ib_dev, 1); ++ rtrs_iu_free(iu, srv_path->s.dev->ib_dev, 1); + return; + close: +- close_sess(sess); ++ close_path(srv_path); + goto out; + } + + static int post_recv_info_req(struct rtrs_srv_con *con) + { +- struct rtrs_sess *s = con->c.sess; +- struct rtrs_srv_sess *sess = to_srv_sess(s); ++ struct rtrs_path *s = con->c.path; ++ struct rtrs_srv_path *srv_path = to_srv_path(s); + struct rtrs_iu *rx_iu; + int err; + + rx_iu = rtrs_iu_alloc(1, sizeof(struct rtrs_msg_info_req), +- GFP_KERNEL, sess->s.dev->ib_dev, ++ GFP_KERNEL, srv_path->s.dev->ib_dev, + DMA_FROM_DEVICE, rtrs_srv_info_req_done); + if (!rx_iu) + return -ENOMEM; +@@ -941,7 +951,7 @@ static int post_recv_info_req(struct rtrs_srv_con *con) + err = rtrs_iu_post_recv(&con->c, rx_iu); + if (err) { + rtrs_err(s, "rtrs_iu_post_recv(), err: %d\n", err); +- rtrs_iu_free(rx_iu, sess->s.dev->ib_dev, 1); ++ rtrs_iu_free(rx_iu, srv_path->s.dev->ib_dev, 1); + return err; + } + +@@ -961,20 +971,20 @@ static int post_recv_io(struct rtrs_srv_con *con, size_t q_size) + return 0; + } + +-static int post_recv_sess(struct rtrs_srv_sess *sess) ++static int post_recv_path(struct rtrs_srv_path *srv_path) + { +- struct rtrs_srv *srv = sess->srv; +- struct rtrs_sess *s = &sess->s; ++ struct rtrs_srv *srv = srv_path->srv; ++ struct rtrs_path *s = &srv_path->s; + size_t q_size; + int err, cid; + +- for (cid = 0; cid < sess->s.con_num; cid++) { ++ for (cid = 0; cid < srv_path->s.con_num; cid++) { + if (cid == 0) + q_size = SERVICE_CON_QUEUE_DEPTH; + else + q_size = srv->queue_depth; + +- err = post_recv_io(to_srv_con(sess->s.con[cid]), q_size); ++ err = post_recv_io(to_srv_con(srv_path->s.con[cid]), q_size); + if (err) { + rtrs_err(s, "post_recv_io(), err: %d\n", err); + return err; +@@ -988,9 +998,9 @@ static void process_read(struct rtrs_srv_con *con, + struct rtrs_msg_rdma_read *msg, + u32 buf_id, u32 off) + { +- struct rtrs_sess *s = con->c.sess; +- struct rtrs_srv_sess *sess = to_srv_sess(s); +- struct rtrs_srv *srv = sess->srv; ++ struct rtrs_path *s = con->c.path; ++ struct rtrs_srv_path *srv_path = to_srv_path(s); ++ struct rtrs_srv *srv = srv_path->srv; + struct rtrs_srv_ctx *ctx = srv->ctx; + struct rtrs_srv_op *id; + +@@ -998,10 +1008,10 @@ static void process_read(struct rtrs_srv_con *con, + void *data; + int ret; + +- if (sess->state != RTRS_SRV_CONNECTED) { ++ if (srv_path->state != RTRS_SRV_CONNECTED) { + rtrs_err_rl(s, + "Processing read request failed, session is disconnected, sess state %s\n", +- rtrs_srv_state_str(sess->state)); ++ rtrs_srv_state_str(srv_path->state)); + return; + } + if (msg->sg_cnt != 1 && msg->sg_cnt != 0) { +@@ -1009,9 +1019,9 @@ static void process_read(struct rtrs_srv_con *con, + "Processing read request failed, invalid message\n"); + return; + } +- rtrs_srv_get_ops_ids(sess); +- rtrs_srv_update_rdma_stats(sess->stats, off, READ); +- id = sess->ops_ids[buf_id]; ++ rtrs_srv_get_ops_ids(srv_path); ++ rtrs_srv_update_rdma_stats(srv_path->stats, off, READ); ++ id = srv_path->ops_ids[buf_id]; + id->con = con; + id->dir = READ; + id->msg_id = buf_id; +@@ -1037,18 +1047,18 @@ send_err_msg: + rtrs_err_rl(s, + "Sending err msg for failed RDMA-Write-Req failed, msg_id %d, err: %d\n", + buf_id, ret); +- close_sess(sess); ++ close_path(srv_path); + } +- rtrs_srv_put_ops_ids(sess); ++ rtrs_srv_put_ops_ids(srv_path); + } + + static void process_write(struct rtrs_srv_con *con, + struct rtrs_msg_rdma_write *req, + u32 buf_id, u32 off) + { +- struct rtrs_sess *s = con->c.sess; +- struct rtrs_srv_sess *sess = to_srv_sess(s); +- struct rtrs_srv *srv = sess->srv; ++ struct rtrs_path *s = con->c.path; ++ struct rtrs_srv_path *srv_path = to_srv_path(s); ++ struct rtrs_srv *srv = srv_path->srv; + struct rtrs_srv_ctx *ctx = srv->ctx; + struct rtrs_srv_op *id; + +@@ -1056,15 +1066,15 @@ static void process_write(struct rtrs_srv_con *con, + void *data; + int ret; + +- if (sess->state != RTRS_SRV_CONNECTED) { ++ if (srv_path->state != RTRS_SRV_CONNECTED) { + rtrs_err_rl(s, + "Processing write request failed, session is disconnected, sess state %s\n", +- rtrs_srv_state_str(sess->state)); ++ rtrs_srv_state_str(srv_path->state)); + return; + } +- rtrs_srv_get_ops_ids(sess); +- rtrs_srv_update_rdma_stats(sess->stats, off, WRITE); +- id = sess->ops_ids[buf_id]; ++ rtrs_srv_get_ops_ids(srv_path); ++ rtrs_srv_update_rdma_stats(srv_path->stats, off, WRITE); ++ id = srv_path->ops_ids[buf_id]; + id->con = con; + id->dir = WRITE; + id->msg_id = buf_id; +@@ -1089,20 +1099,21 @@ send_err_msg: + rtrs_err_rl(s, + "Processing write request failed, sending I/O response failed, msg_id %d, err: %d\n", + buf_id, ret); +- close_sess(sess); ++ close_path(srv_path); + } +- rtrs_srv_put_ops_ids(sess); ++ rtrs_srv_put_ops_ids(srv_path); + } + + static void process_io_req(struct rtrs_srv_con *con, void *msg, + u32 id, u32 off) + { +- struct rtrs_sess *s = con->c.sess; +- struct rtrs_srv_sess *sess = to_srv_sess(s); ++ struct rtrs_path *s = con->c.path; ++ struct rtrs_srv_path *srv_path = to_srv_path(s); + struct rtrs_msg_rdma_hdr *hdr; + unsigned int type; + +- ib_dma_sync_single_for_cpu(sess->s.dev->ib_dev, sess->dma_addr[id], ++ ib_dma_sync_single_for_cpu(srv_path->s.dev->ib_dev, ++ srv_path->dma_addr[id], + max_chunk_size, DMA_BIDIRECTIONAL); + hdr = msg; + type = le16_to_cpu(hdr->type); +@@ -1124,7 +1135,7 @@ static void process_io_req(struct rtrs_srv_con *con, void *msg, + return; + + err: +- close_sess(sess); ++ close_path(srv_path); + } + + static void rtrs_srv_inv_rkey_done(struct ib_cq *cq, struct ib_wc *wc) +@@ -1132,16 +1143,16 @@ static void rtrs_srv_inv_rkey_done(struct ib_cq *cq, struct ib_wc *wc) + struct rtrs_srv_mr *mr = + container_of(wc->wr_cqe, typeof(*mr), inv_cqe); + struct rtrs_srv_con *con = to_srv_con(wc->qp->qp_context); +- struct rtrs_sess *s = con->c.sess; +- struct rtrs_srv_sess *sess = to_srv_sess(s); +- struct rtrs_srv *srv = sess->srv; ++ struct rtrs_path *s = con->c.path; ++ struct rtrs_srv_path *srv_path = to_srv_path(s); ++ struct rtrs_srv *srv = srv_path->srv; + u32 msg_id, off; + void *data; + + if (wc->status != IB_WC_SUCCESS) { + rtrs_err(s, "Failed IB_WR_LOCAL_INV: %s\n", + ib_wc_status_msg(wc->status)); +- close_sess(sess); ++ close_path(srv_path); + } + msg_id = mr->msg_id; + off = mr->msg_off; +@@ -1189,9 +1200,9 @@ static void rtrs_rdma_process_wr_wait_list(struct rtrs_srv_con *con) + static void rtrs_srv_rdma_done(struct ib_cq *cq, struct ib_wc *wc) + { + struct rtrs_srv_con *con = to_srv_con(wc->qp->qp_context); +- struct rtrs_sess *s = con->c.sess; +- struct rtrs_srv_sess *sess = to_srv_sess(s); +- struct rtrs_srv *srv = sess->srv; ++ struct rtrs_path *s = con->c.path; ++ struct rtrs_srv_path *srv_path = to_srv_path(s); ++ struct rtrs_srv *srv = srv_path->srv; + u32 imm_type, imm_payload; + int err; + +@@ -1201,7 +1212,7 @@ static void rtrs_srv_rdma_done(struct ib_cq *cq, struct ib_wc *wc) + "%s (wr_cqe: %p, type: %d, vendor_err: 0x%x, len: %u)\n", + ib_wc_status_msg(wc->status), wc->wr_cqe, + wc->opcode, wc->vendor_err, wc->byte_len); +- close_sess(sess); ++ close_path(srv_path); + } + return; + } +@@ -1217,7 +1228,7 @@ static void rtrs_srv_rdma_done(struct ib_cq *cq, struct ib_wc *wc) + err = rtrs_post_recv_empty(&con->c, &io_comp_cqe); + if (err) { + rtrs_err(s, "rtrs_post_recv(), err: %d\n", err); +- close_sess(sess); ++ close_path(srv_path); + break; + } + rtrs_from_imm(be32_to_cpu(wc->ex.imm_data), +@@ -1226,16 +1237,16 @@ static void rtrs_srv_rdma_done(struct ib_cq *cq, struct ib_wc *wc) + u32 msg_id, off; + void *data; + +- msg_id = imm_payload >> sess->mem_bits; +- off = imm_payload & ((1 << sess->mem_bits) - 1); ++ msg_id = imm_payload >> srv_path->mem_bits; ++ off = imm_payload & ((1 << srv_path->mem_bits) - 1); + if (msg_id >= srv->queue_depth || off >= max_chunk_size) { + rtrs_err(s, "Wrong msg_id %u, off %u\n", + msg_id, off); +- close_sess(sess); ++ close_path(srv_path); + return; + } + if (always_invalidate) { +- struct rtrs_srv_mr *mr = &sess->mrs[msg_id]; ++ struct rtrs_srv_mr *mr = &srv_path->mrs[msg_id]; + + mr->msg_off = off; + mr->msg_id = msg_id; +@@ -1243,7 +1254,7 @@ static void rtrs_srv_rdma_done(struct ib_cq *cq, struct ib_wc *wc) + if (err) { + rtrs_err(s, "rtrs_post_recv(), err: %d\n", + err); +- close_sess(sess); ++ close_path(srv_path); + break; + } + } else { +@@ -1252,10 +1263,10 @@ static void rtrs_srv_rdma_done(struct ib_cq *cq, struct ib_wc *wc) + } + } else if (imm_type == RTRS_HB_MSG_IMM) { + WARN_ON(con->c.cid); +- rtrs_send_hb_ack(&sess->s); ++ rtrs_send_hb_ack(&srv_path->s); + } else if (imm_type == RTRS_HB_ACK_IMM) { + WARN_ON(con->c.cid); +- sess->s.hb_missed_cnt = 0; ++ srv_path->s.hb_missed_cnt = 0; + } else { + rtrs_wrn(s, "Unknown IMM type %u\n", imm_type); + } +@@ -1279,22 +1290,23 @@ static void rtrs_srv_rdma_done(struct ib_cq *cq, struct ib_wc *wc) + } + + /** +- * rtrs_srv_get_sess_name() - Get rtrs_srv peer hostname. ++ * rtrs_srv_get_path_name() - Get rtrs_srv peer hostname. + * @srv: Session +- * @sessname: Sessname buffer ++ * @pathname: Pathname buffer + * @len: Length of sessname buffer + */ +-int rtrs_srv_get_sess_name(struct rtrs_srv *srv, char *sessname, size_t len) ++int rtrs_srv_get_path_name(struct rtrs_srv *srv, char *pathname, ++ size_t len) + { +- struct rtrs_srv_sess *sess; ++ struct rtrs_srv_path *srv_path; + int err = -ENOTCONN; + + mutex_lock(&srv->paths_mutex); +- list_for_each_entry(sess, &srv->paths_list, s.entry) { +- if (sess->state != RTRS_SRV_CONNECTED) ++ list_for_each_entry(srv_path, &srv->paths_list, s.entry) { ++ if (srv_path->state != RTRS_SRV_CONNECTED) + continue; +- strscpy(sessname, sess->s.sessname, +- min_t(size_t, sizeof(sess->s.sessname), len)); ++ strscpy(pathname, srv_path->s.sessname, ++ min_t(size_t, sizeof(srv_path->s.sessname), len)); + err = 0; + break; + } +@@ -1302,7 +1314,7 @@ int rtrs_srv_get_sess_name(struct rtrs_srv *srv, char *sessname, size_t len) + + return err; + } +-EXPORT_SYMBOL(rtrs_srv_get_sess_name); ++EXPORT_SYMBOL(rtrs_srv_get_path_name); + + /** + * rtrs_srv_get_queue_depth() - Get rtrs_srv qdepth. +@@ -1314,22 +1326,22 @@ int rtrs_srv_get_queue_depth(struct rtrs_srv *srv) + } + EXPORT_SYMBOL(rtrs_srv_get_queue_depth); + +-static int find_next_bit_ring(struct rtrs_srv_sess *sess) ++static int find_next_bit_ring(struct rtrs_srv_path *srv_path) + { +- struct ib_device *ib_dev = sess->s.dev->ib_dev; ++ struct ib_device *ib_dev = srv_path->s.dev->ib_dev; + int v; + +- v = cpumask_next(sess->cur_cq_vector, &cq_affinity_mask); ++ v = cpumask_next(srv_path->cur_cq_vector, &cq_affinity_mask); + if (v >= nr_cpu_ids || v >= ib_dev->num_comp_vectors) + v = cpumask_first(&cq_affinity_mask); + return v; + } + +-static int rtrs_srv_get_next_cq_vector(struct rtrs_srv_sess *sess) ++static int rtrs_srv_get_next_cq_vector(struct rtrs_srv_path *srv_path) + { +- sess->cur_cq_vector = find_next_bit_ring(sess); ++ srv_path->cur_cq_vector = find_next_bit_ring(srv_path); + +- return sess->cur_cq_vector; ++ return srv_path->cur_cq_vector; + } + + static void rtrs_srv_dev_release(struct device *dev) +@@ -1434,22 +1446,22 @@ static void put_srv(struct rtrs_srv *srv) + } + + static void __add_path_to_srv(struct rtrs_srv *srv, +- struct rtrs_srv_sess *sess) ++ struct rtrs_srv_path *srv_path) + { +- list_add_tail(&sess->s.entry, &srv->paths_list); ++ list_add_tail(&srv_path->s.entry, &srv->paths_list); + srv->paths_num++; + WARN_ON(srv->paths_num >= MAX_PATHS_NUM); + } + +-static void del_path_from_srv(struct rtrs_srv_sess *sess) ++static void del_path_from_srv(struct rtrs_srv_path *srv_path) + { +- struct rtrs_srv *srv = sess->srv; ++ struct rtrs_srv *srv = srv_path->srv; + + if (WARN_ON(!srv)) + return; + + mutex_lock(&srv->paths_mutex); +- list_del(&sess->s.entry); ++ list_del(&srv_path->s.entry); + WARN_ON(!srv->paths_num); + srv->paths_num--; + mutex_unlock(&srv->paths_mutex); +@@ -1482,44 +1494,44 @@ static int sockaddr_cmp(const struct sockaddr *a, const struct sockaddr *b) + static bool __is_path_w_addr_exists(struct rtrs_srv *srv, + struct rdma_addr *addr) + { +- struct rtrs_srv_sess *sess; ++ struct rtrs_srv_path *srv_path; + +- list_for_each_entry(sess, &srv->paths_list, s.entry) +- if (!sockaddr_cmp((struct sockaddr *)&sess->s.dst_addr, ++ list_for_each_entry(srv_path, &srv->paths_list, s.entry) ++ if (!sockaddr_cmp((struct sockaddr *)&srv_path->s.dst_addr, + (struct sockaddr *)&addr->dst_addr) && +- !sockaddr_cmp((struct sockaddr *)&sess->s.src_addr, ++ !sockaddr_cmp((struct sockaddr *)&srv_path->s.src_addr, + (struct sockaddr *)&addr->src_addr)) + return true; + + return false; + } + +-static void free_sess(struct rtrs_srv_sess *sess) ++static void free_path(struct rtrs_srv_path *srv_path) + { +- if (sess->kobj.state_in_sysfs) { +- kobject_del(&sess->kobj); +- kobject_put(&sess->kobj); ++ if (srv_path->kobj.state_in_sysfs) { ++ kobject_del(&srv_path->kobj); ++ kobject_put(&srv_path->kobj); + } else { +- kfree(sess->stats); +- kfree(sess); ++ kfree(srv_path->stats); ++ kfree(srv_path); + } + } + + static void rtrs_srv_close_work(struct work_struct *work) + { +- struct rtrs_srv_sess *sess; ++ struct rtrs_srv_path *srv_path; + struct rtrs_srv_con *con; + int i; + +- sess = container_of(work, typeof(*sess), close_work); ++ srv_path = container_of(work, typeof(*srv_path), close_work); + +- rtrs_srv_destroy_sess_files(sess); +- rtrs_srv_stop_hb(sess); ++ rtrs_srv_destroy_path_files(srv_path); ++ rtrs_srv_stop_hb(srv_path); + +- for (i = 0; i < sess->s.con_num; i++) { +- if (!sess->s.con[i]) ++ for (i = 0; i < srv_path->s.con_num; i++) { ++ if (!srv_path->s.con[i]) + continue; +- con = to_srv_con(sess->s.con[i]); ++ con = to_srv_con(srv_path->s.con[i]); + rdma_disconnect(con->c.cm_id); + ib_drain_qp(con->c.qp); + } +@@ -1528,41 +1540,41 @@ static void rtrs_srv_close_work(struct work_struct *work) + * Degrade ref count to the usual model with a single shared + * atomic_t counter + */ +- percpu_ref_kill(&sess->ids_inflight_ref); ++ percpu_ref_kill(&srv_path->ids_inflight_ref); + + /* Wait for all completion */ +- wait_for_completion(&sess->complete_done); ++ wait_for_completion(&srv_path->complete_done); + + /* Notify upper layer if we are the last path */ +- rtrs_srv_sess_down(sess); ++ rtrs_srv_path_down(srv_path); + +- unmap_cont_bufs(sess); +- rtrs_srv_free_ops_ids(sess); ++ unmap_cont_bufs(srv_path); ++ rtrs_srv_free_ops_ids(srv_path); + +- for (i = 0; i < sess->s.con_num; i++) { +- if (!sess->s.con[i]) ++ for (i = 0; i < srv_path->s.con_num; i++) { ++ if (!srv_path->s.con[i]) + continue; +- con = to_srv_con(sess->s.con[i]); ++ con = to_srv_con(srv_path->s.con[i]); + rtrs_cq_qp_destroy(&con->c); + rdma_destroy_id(con->c.cm_id); + kfree(con); + } +- rtrs_ib_dev_put(sess->s.dev); ++ rtrs_ib_dev_put(srv_path->s.dev); + +- del_path_from_srv(sess); +- put_srv(sess->srv); +- sess->srv = NULL; +- rtrs_srv_change_state(sess, RTRS_SRV_CLOSED); ++ del_path_from_srv(srv_path); ++ put_srv(srv_path->srv); ++ srv_path->srv = NULL; ++ rtrs_srv_change_state(srv_path, RTRS_SRV_CLOSED); + +- kfree(sess->dma_addr); +- kfree(sess->s.con); +- free_sess(sess); ++ kfree(srv_path->dma_addr); ++ kfree(srv_path->s.con); ++ free_path(srv_path); + } + +-static int rtrs_rdma_do_accept(struct rtrs_srv_sess *sess, ++static int rtrs_rdma_do_accept(struct rtrs_srv_path *srv_path, + struct rdma_cm_id *cm_id) + { +- struct rtrs_srv *srv = sess->srv; ++ struct rtrs_srv *srv = srv_path->srv; + struct rtrs_msg_conn_rsp msg; + struct rdma_conn_param param; + int err; +@@ -1610,25 +1622,25 @@ static int rtrs_rdma_do_reject(struct rdma_cm_id *cm_id, int errno) + return errno; + } + +-static struct rtrs_srv_sess * +-__find_sess(struct rtrs_srv *srv, const uuid_t *sess_uuid) ++static struct rtrs_srv_path * ++__find_path(struct rtrs_srv *srv, const uuid_t *sess_uuid) + { +- struct rtrs_srv_sess *sess; ++ struct rtrs_srv_path *srv_path; + +- list_for_each_entry(sess, &srv->paths_list, s.entry) { +- if (uuid_equal(&sess->s.uuid, sess_uuid)) +- return sess; ++ list_for_each_entry(srv_path, &srv->paths_list, s.entry) { ++ if (uuid_equal(&srv_path->s.uuid, sess_uuid)) ++ return srv_path; + } + + return NULL; + } + +-static int create_con(struct rtrs_srv_sess *sess, ++static int create_con(struct rtrs_srv_path *srv_path, + struct rdma_cm_id *cm_id, + unsigned int cid) + { +- struct rtrs_srv *srv = sess->srv; +- struct rtrs_sess *s = &sess->s; ++ struct rtrs_srv *srv = srv_path->srv; ++ struct rtrs_path *s = &srv_path->s; + struct rtrs_srv_con *con; + + u32 cq_num, max_send_wr, max_recv_wr, wr_limit; +@@ -1643,10 +1655,10 @@ static int create_con(struct rtrs_srv_sess *sess, + spin_lock_init(&con->rsp_wr_wait_lock); + INIT_LIST_HEAD(&con->rsp_wr_wait_list); + con->c.cm_id = cm_id; +- con->c.sess = &sess->s; ++ con->c.path = &srv_path->s; + con->c.cid = cid; + atomic_set(&con->c.wr_cnt, 1); +- wr_limit = sess->s.dev->ib_dev->attrs.max_qp_wr; ++ wr_limit = srv_path->s.dev->ib_dev->attrs.max_qp_wr; + + if (con->c.cid == 0) { + /* +@@ -1679,10 +1691,10 @@ static int create_con(struct rtrs_srv_sess *sess, + } + cq_num = max_send_wr + max_recv_wr; + atomic_set(&con->c.sq_wr_avail, max_send_wr); +- cq_vector = rtrs_srv_get_next_cq_vector(sess); ++ cq_vector = rtrs_srv_get_next_cq_vector(srv_path); + + /* TODO: SOFTIRQ can be faster, but be careful with softirq context */ +- err = rtrs_cq_qp_create(&sess->s, &con->c, 1, cq_vector, cq_num, ++ err = rtrs_cq_qp_create(&srv_path->s, &con->c, 1, cq_vector, cq_num, + max_send_wr, max_recv_wr, + IB_POLL_WORKQUEUE); + if (err) { +@@ -1694,8 +1706,8 @@ static int create_con(struct rtrs_srv_sess *sess, + if (err) + goto free_cqqp; + } +- WARN_ON(sess->s.con[cid]); +- sess->s.con[cid] = &con->c; ++ WARN_ON(srv_path->s.con[cid]); ++ srv_path->s.con[cid] = &con->c; + + /* + * Change context from server to current connection. The other +@@ -1714,13 +1726,13 @@ err: + return err; + } + +-static struct rtrs_srv_sess *__alloc_sess(struct rtrs_srv *srv, ++static struct rtrs_srv_path *__alloc_path(struct rtrs_srv *srv, + struct rdma_cm_id *cm_id, + unsigned int con_num, + unsigned int recon_cnt, + const uuid_t *uuid) + { +- struct rtrs_srv_sess *sess; ++ struct rtrs_srv_path *srv_path; + int err = -ENOMEM; + char str[NAME_MAX]; + struct rtrs_addr path; +@@ -1734,73 +1746,76 @@ static struct rtrs_srv_sess *__alloc_sess(struct rtrs_srv *srv, + pr_err("Path with same addr exists\n"); + goto err; + } +- sess = kzalloc(sizeof(*sess), GFP_KERNEL); +- if (!sess) ++ srv_path = kzalloc(sizeof(*srv_path), GFP_KERNEL); ++ if (!srv_path) + goto err; + +- sess->stats = kzalloc(sizeof(*sess->stats), GFP_KERNEL); +- if (!sess->stats) ++ srv_path->stats = kzalloc(sizeof(*srv_path->stats), GFP_KERNEL); ++ if (!srv_path->stats) + goto err_free_sess; + +- sess->stats->sess = sess; ++ srv_path->stats->srv_path = srv_path; + +- sess->dma_addr = kcalloc(srv->queue_depth, sizeof(*sess->dma_addr), +- GFP_KERNEL); +- if (!sess->dma_addr) ++ srv_path->dma_addr = kcalloc(srv->queue_depth, ++ sizeof(*srv_path->dma_addr), ++ GFP_KERNEL); ++ if (!srv_path->dma_addr) + goto err_free_stats; + +- sess->s.con = kcalloc(con_num, sizeof(*sess->s.con), GFP_KERNEL); +- if (!sess->s.con) ++ srv_path->s.con = kcalloc(con_num, sizeof(*srv_path->s.con), ++ GFP_KERNEL); ++ if (!srv_path->s.con) + goto err_free_dma_addr; + +- sess->state = RTRS_SRV_CONNECTING; +- sess->srv = srv; +- sess->cur_cq_vector = -1; +- sess->s.dst_addr = cm_id->route.addr.dst_addr; +- sess->s.src_addr = cm_id->route.addr.src_addr; ++ srv_path->state = RTRS_SRV_CONNECTING; ++ srv_path->srv = srv; ++ srv_path->cur_cq_vector = -1; ++ srv_path->s.dst_addr = cm_id->route.addr.dst_addr; ++ srv_path->s.src_addr = cm_id->route.addr.src_addr; + + /* temporary until receiving session-name from client */ +- path.src = &sess->s.src_addr; +- path.dst = &sess->s.dst_addr; ++ path.src = &srv_path->s.src_addr; ++ path.dst = &srv_path->s.dst_addr; + rtrs_addr_to_str(&path, str, sizeof(str)); +- strscpy(sess->s.sessname, str, sizeof(sess->s.sessname)); +- +- sess->s.con_num = con_num; +- sess->s.recon_cnt = recon_cnt; +- uuid_copy(&sess->s.uuid, uuid); +- spin_lock_init(&sess->state_lock); +- INIT_WORK(&sess->close_work, rtrs_srv_close_work); +- rtrs_srv_init_hb(sess); +- +- sess->s.dev = rtrs_ib_dev_find_or_add(cm_id->device, &dev_pd); +- if (!sess->s.dev) { ++ strscpy(srv_path->s.sessname, str, sizeof(srv_path->s.sessname)); ++ ++ srv_path->s.con_num = con_num; ++ srv_path->s.irq_con_num = con_num; ++ srv_path->s.recon_cnt = recon_cnt; ++ uuid_copy(&srv_path->s.uuid, uuid); ++ spin_lock_init(&srv_path->state_lock); ++ INIT_WORK(&srv_path->close_work, rtrs_srv_close_work); ++ rtrs_srv_init_hb(srv_path); ++ ++ srv_path->s.dev = rtrs_ib_dev_find_or_add(cm_id->device, &dev_pd); ++ if (!srv_path->s.dev) { + err = -ENOMEM; + goto err_free_con; + } +- err = map_cont_bufs(sess); ++ err = map_cont_bufs(srv_path); + if (err) + goto err_put_dev; + +- err = rtrs_srv_alloc_ops_ids(sess); ++ err = rtrs_srv_alloc_ops_ids(srv_path); + if (err) + goto err_unmap_bufs; + +- __add_path_to_srv(srv, sess); ++ __add_path_to_srv(srv, srv_path); + +- return sess; ++ return srv_path; + + err_unmap_bufs: +- unmap_cont_bufs(sess); ++ unmap_cont_bufs(srv_path); + err_put_dev: +- rtrs_ib_dev_put(sess->s.dev); ++ rtrs_ib_dev_put(srv_path->s.dev); + err_free_con: +- kfree(sess->s.con); ++ kfree(srv_path->s.con); + err_free_dma_addr: +- kfree(sess->dma_addr); ++ kfree(srv_path->dma_addr); + err_free_stats: +- kfree(sess->stats); ++ kfree(srv_path->stats); + err_free_sess: +- kfree(sess); ++ kfree(srv_path); + err: + return ERR_PTR(err); + } +@@ -1810,7 +1825,7 @@ static int rtrs_rdma_connect(struct rdma_cm_id *cm_id, + size_t len) + { + struct rtrs_srv_ctx *ctx = cm_id->context; +- struct rtrs_srv_sess *sess; ++ struct rtrs_srv_path *srv_path; + struct rtrs_srv *srv; + + u16 version, con_num, cid; +@@ -1851,16 +1866,16 @@ static int rtrs_rdma_connect(struct rdma_cm_id *cm_id, + goto reject_w_err; + } + mutex_lock(&srv->paths_mutex); +- sess = __find_sess(srv, &msg->sess_uuid); +- if (sess) { +- struct rtrs_sess *s = &sess->s; ++ srv_path = __find_path(srv, &msg->sess_uuid); ++ if (srv_path) { ++ struct rtrs_path *s = &srv_path->s; + + /* Session already holds a reference */ + put_srv(srv); + +- if (sess->state != RTRS_SRV_CONNECTING) { ++ if (srv_path->state != RTRS_SRV_CONNECTING) { + rtrs_err(s, "Session in wrong state: %s\n", +- rtrs_srv_state_str(sess->state)); ++ rtrs_srv_state_str(srv_path->state)); + mutex_unlock(&srv->paths_mutex); + goto reject_w_err; + } +@@ -1880,19 +1895,19 @@ static int rtrs_rdma_connect(struct rdma_cm_id *cm_id, + goto reject_w_err; + } + } else { +- sess = __alloc_sess(srv, cm_id, con_num, recon_cnt, ++ srv_path = __alloc_path(srv, cm_id, con_num, recon_cnt, + &msg->sess_uuid); +- if (IS_ERR(sess)) { ++ if (IS_ERR(srv_path)) { + mutex_unlock(&srv->paths_mutex); + put_srv(srv); +- err = PTR_ERR(sess); ++ err = PTR_ERR(srv_path); + pr_err("RTRS server session allocation failed: %d\n", err); + goto reject_w_err; + } + } +- err = create_con(sess, cm_id, cid); ++ err = create_con(srv_path, cm_id, cid); + if (err) { +- rtrs_err((&sess->s), "create_con(), error %d\n", err); ++ rtrs_err((&srv_path->s), "create_con(), error %d\n", err); + rtrs_rdma_do_reject(cm_id, err); + /* + * Since session has other connections we follow normal way +@@ -1901,9 +1916,9 @@ static int rtrs_rdma_connect(struct rdma_cm_id *cm_id, + */ + goto close_and_return_err; + } +- err = rtrs_rdma_do_accept(sess, cm_id); ++ err = rtrs_rdma_do_accept(srv_path, cm_id); + if (err) { +- rtrs_err((&sess->s), "rtrs_rdma_do_accept(), error %d\n", err); ++ rtrs_err((&srv_path->s), "rtrs_rdma_do_accept(), error %d\n", err); + rtrs_rdma_do_reject(cm_id, err); + /* + * Since current connection was successfully added to the +@@ -1923,7 +1938,7 @@ reject_w_err: + + close_and_return_err: + mutex_unlock(&srv->paths_mutex); +- close_sess(sess); ++ close_path(srv_path); + + return err; + } +@@ -1931,14 +1946,14 @@ close_and_return_err: + static int rtrs_srv_rdma_cm_handler(struct rdma_cm_id *cm_id, + struct rdma_cm_event *ev) + { +- struct rtrs_srv_sess *sess = NULL; +- struct rtrs_sess *s = NULL; ++ struct rtrs_srv_path *srv_path = NULL; ++ struct rtrs_path *s = NULL; + + if (ev->event != RDMA_CM_EVENT_CONNECT_REQUEST) { + struct rtrs_con *c = cm_id->context; + +- s = c->sess; +- sess = to_srv_sess(s); ++ s = c->path; ++ srv_path = to_srv_path(s); + } + + switch (ev->event) { +@@ -1962,7 +1977,7 @@ static int rtrs_srv_rdma_cm_handler(struct rdma_cm_id *cm_id, + case RDMA_CM_EVENT_ADDR_CHANGE: + case RDMA_CM_EVENT_TIMEWAIT_EXIT: + case RDMA_CM_EVENT_DEVICE_REMOVAL: +- close_sess(sess); ++ close_path(srv_path); + break; + default: + pr_err("Ignoring unexpected CM event %s, err %d\n", +@@ -2170,13 +2185,13 @@ struct rtrs_srv_ctx *rtrs_srv_open(struct rtrs_srv_ops *ops, u16 port) + } + EXPORT_SYMBOL(rtrs_srv_open); + +-static void close_sessions(struct rtrs_srv *srv) ++static void close_paths(struct rtrs_srv *srv) + { +- struct rtrs_srv_sess *sess; ++ struct rtrs_srv_path *srv_path; + + mutex_lock(&srv->paths_mutex); +- list_for_each_entry(sess, &srv->paths_list, s.entry) +- close_sess(sess); ++ list_for_each_entry(srv_path, &srv->paths_list, s.entry) ++ close_path(srv_path); + mutex_unlock(&srv->paths_mutex); + } + +@@ -2186,7 +2201,7 @@ static void close_ctx(struct rtrs_srv_ctx *ctx) + + mutex_lock(&ctx->srv_mutex); + list_for_each_entry(srv, &ctx->srv_list, ctx_list) +- close_sessions(srv); ++ close_paths(srv); + mutex_unlock(&ctx->srv_mutex); + flush_workqueue(rtrs_wq); + } +diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.h b/drivers/infiniband/ulp/rtrs/rtrs-srv.h +index 9d8d2a91a235b..ee3578b9aa01f 100644 +--- a/drivers/infiniband/ulp/rtrs/rtrs-srv.h ++++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.h +@@ -37,7 +37,7 @@ struct rtrs_srv_stats_rdma_stats { + struct rtrs_srv_stats { + struct kobject kobj_stats; + struct rtrs_srv_stats_rdma_stats rdma_stats; +- struct rtrs_srv_sess *sess; ++ struct rtrs_srv_path *srv_path; + }; + + struct rtrs_srv_con { +@@ -71,8 +71,8 @@ struct rtrs_srv_mr { + struct rtrs_iu *iu; /* send buffer for new rkey msg */ + }; + +-struct rtrs_srv_sess { +- struct rtrs_sess s; ++struct rtrs_srv_path { ++ struct rtrs_path s; + struct rtrs_srv *srv; + struct work_struct close_work; + enum rtrs_srv_state state; +@@ -125,7 +125,7 @@ struct rtrs_srv_ib_ctx { + + extern struct class *rtrs_dev_class; + +-void close_sess(struct rtrs_srv_sess *sess); ++void close_path(struct rtrs_srv_path *srv_path); + + static inline void rtrs_srv_update_rdma_stats(struct rtrs_srv_stats *s, + size_t size, int d) +@@ -143,7 +143,7 @@ ssize_t rtrs_srv_reset_all_help(struct rtrs_srv_stats *stats, + char *page, size_t len); + + /* functions which are implemented in rtrs-srv-sysfs.c */ +-int rtrs_srv_create_sess_files(struct rtrs_srv_sess *sess); +-void rtrs_srv_destroy_sess_files(struct rtrs_srv_sess *sess); ++int rtrs_srv_create_path_files(struct rtrs_srv_path *srv_path); ++void rtrs_srv_destroy_path_files(struct rtrs_srv_path *srv_path); + + #endif /* RTRS_SRV_H */ +diff --git a/drivers/infiniband/ulp/rtrs/rtrs.c b/drivers/infiniband/ulp/rtrs/rtrs.c +index ca542e477d384..4da889103a5ff 100644 +--- a/drivers/infiniband/ulp/rtrs/rtrs.c ++++ b/drivers/infiniband/ulp/rtrs/rtrs.c +@@ -69,16 +69,16 @@ EXPORT_SYMBOL_GPL(rtrs_iu_free); + + int rtrs_iu_post_recv(struct rtrs_con *con, struct rtrs_iu *iu) + { +- struct rtrs_sess *sess = con->sess; ++ struct rtrs_path *path = con->path; + struct ib_recv_wr wr; + struct ib_sge list; + + list.addr = iu->dma_addr; + list.length = iu->size; +- list.lkey = sess->dev->ib_pd->local_dma_lkey; ++ list.lkey = path->dev->ib_pd->local_dma_lkey; + + if (list.length == 0) { +- rtrs_wrn(con->sess, ++ rtrs_wrn(con->path, + "Posting receive work request failed, sg list is empty\n"); + return -EINVAL; + } +@@ -126,7 +126,7 @@ static int rtrs_post_send(struct ib_qp *qp, struct ib_send_wr *head, + int rtrs_iu_post_send(struct rtrs_con *con, struct rtrs_iu *iu, size_t size, + struct ib_send_wr *head) + { +- struct rtrs_sess *sess = con->sess; ++ struct rtrs_path *path = con->path; + struct ib_send_wr wr; + struct ib_sge list; + +@@ -135,7 +135,7 @@ int rtrs_iu_post_send(struct rtrs_con *con, struct rtrs_iu *iu, size_t size, + + list.addr = iu->dma_addr; + list.length = size; +- list.lkey = sess->dev->ib_pd->local_dma_lkey; ++ list.lkey = path->dev->ib_pd->local_dma_lkey; + + wr = (struct ib_send_wr) { + .wr_cqe = &iu->cqe, +@@ -188,11 +188,11 @@ static int rtrs_post_rdma_write_imm_empty(struct rtrs_con *con, + struct ib_send_wr *head) + { + struct ib_rdma_wr wr; +- struct rtrs_sess *sess = con->sess; ++ struct rtrs_path *path = con->path; + enum ib_send_flags sflags; + + atomic_dec_if_positive(&con->sq_wr_avail); +- sflags = (atomic_inc_return(&con->wr_cnt) % sess->signal_interval) ? ++ sflags = (atomic_inc_return(&con->wr_cnt) % path->signal_interval) ? + 0 : IB_SEND_SIGNALED; + + wr = (struct ib_rdma_wr) { +@@ -211,26 +211,36 @@ static void qp_event_handler(struct ib_event *ev, void *ctx) + + switch (ev->event) { + case IB_EVENT_COMM_EST: +- rtrs_info(con->sess, "QP event %s (%d) received\n", ++ rtrs_info(con->path, "QP event %s (%d) received\n", + ib_event_msg(ev->event), ev->event); + rdma_notify(con->cm_id, IB_EVENT_COMM_EST); + break; + default: +- rtrs_info(con->sess, "Unhandled QP event %s (%d) received\n", ++ rtrs_info(con->path, "Unhandled QP event %s (%d) received\n", + ib_event_msg(ev->event), ev->event); + break; + } + } + ++static bool is_pollqueue(struct rtrs_con *con) ++{ ++ return con->cid >= con->path->irq_con_num; ++} ++ + static int create_cq(struct rtrs_con *con, int cq_vector, int nr_cqe, + enum ib_poll_context poll_ctx) + { + struct rdma_cm_id *cm_id = con->cm_id; + struct ib_cq *cq; + +- cq = ib_cq_pool_get(cm_id->device, nr_cqe, cq_vector, poll_ctx); ++ if (is_pollqueue(con)) ++ cq = ib_alloc_cq(cm_id->device, con, nr_cqe, cq_vector, ++ poll_ctx); ++ else ++ cq = ib_cq_pool_get(cm_id->device, nr_cqe, cq_vector, poll_ctx); ++ + if (IS_ERR(cq)) { +- rtrs_err(con->sess, "Creating completion queue failed, errno: %ld\n", ++ rtrs_err(con->path, "Creating completion queue failed, errno: %ld\n", + PTR_ERR(cq)); + return PTR_ERR(cq); + } +@@ -261,7 +271,7 @@ static int create_qp(struct rtrs_con *con, struct ib_pd *pd, + + ret = rdma_create_qp(cm_id, pd, &init_attr); + if (ret) { +- rtrs_err(con->sess, "Creating QP failed, err: %d\n", ret); ++ rtrs_err(con->path, "Creating QP failed, err: %d\n", ret); + return ret; + } + con->qp = cm_id->qp; +@@ -269,7 +279,18 @@ static int create_qp(struct rtrs_con *con, struct ib_pd *pd, + return ret; + } + +-int rtrs_cq_qp_create(struct rtrs_sess *sess, struct rtrs_con *con, ++static void destroy_cq(struct rtrs_con *con) ++{ ++ if (con->cq) { ++ if (is_pollqueue(con)) ++ ib_free_cq(con->cq); ++ else ++ ib_cq_pool_put(con->cq, con->nr_cqe); ++ } ++ con->cq = NULL; ++} ++ ++int rtrs_cq_qp_create(struct rtrs_path *path, struct rtrs_con *con, + u32 max_send_sge, int cq_vector, int nr_cqe, + u32 max_send_wr, u32 max_recv_wr, + enum ib_poll_context poll_ctx) +@@ -280,14 +301,13 @@ int rtrs_cq_qp_create(struct rtrs_sess *sess, struct rtrs_con *con, + if (err) + return err; + +- err = create_qp(con, sess->dev->ib_pd, max_send_wr, max_recv_wr, ++ err = create_qp(con, path->dev->ib_pd, max_send_wr, max_recv_wr, + max_send_sge); + if (err) { +- ib_cq_pool_put(con->cq, con->nr_cqe); +- con->cq = NULL; ++ destroy_cq(con); + return err; + } +- con->sess = sess; ++ con->path = path; + + return 0; + } +@@ -299,31 +319,28 @@ void rtrs_cq_qp_destroy(struct rtrs_con *con) + rdma_destroy_qp(con->cm_id); + con->qp = NULL; + } +- if (con->cq) { +- ib_cq_pool_put(con->cq, con->nr_cqe); +- con->cq = NULL; +- } ++ destroy_cq(con); + } + EXPORT_SYMBOL_GPL(rtrs_cq_qp_destroy); + +-static void schedule_hb(struct rtrs_sess *sess) ++static void schedule_hb(struct rtrs_path *path) + { +- queue_delayed_work(sess->hb_wq, &sess->hb_dwork, +- msecs_to_jiffies(sess->hb_interval_ms)); ++ queue_delayed_work(path->hb_wq, &path->hb_dwork, ++ msecs_to_jiffies(path->hb_interval_ms)); + } + +-void rtrs_send_hb_ack(struct rtrs_sess *sess) ++void rtrs_send_hb_ack(struct rtrs_path *path) + { +- struct rtrs_con *usr_con = sess->con[0]; ++ struct rtrs_con *usr_con = path->con[0]; + u32 imm; + int err; + + imm = rtrs_to_imm(RTRS_HB_ACK_IMM, 0); +- err = rtrs_post_rdma_write_imm_empty(usr_con, sess->hb_cqe, imm, ++ err = rtrs_post_rdma_write_imm_empty(usr_con, path->hb_cqe, imm, + NULL); + if (err) { +- rtrs_err(sess, "send HB ACK failed, errno: %d\n", err); +- sess->hb_err_handler(usr_con); ++ rtrs_err(path, "send HB ACK failed, errno: %d\n", err); ++ path->hb_err_handler(usr_con); + return; + } + } +@@ -332,63 +349,63 @@ EXPORT_SYMBOL_GPL(rtrs_send_hb_ack); + static void hb_work(struct work_struct *work) + { + struct rtrs_con *usr_con; +- struct rtrs_sess *sess; ++ struct rtrs_path *path; + u32 imm; + int err; + +- sess = container_of(to_delayed_work(work), typeof(*sess), hb_dwork); +- usr_con = sess->con[0]; ++ path = container_of(to_delayed_work(work), typeof(*path), hb_dwork); ++ usr_con = path->con[0]; + +- if (sess->hb_missed_cnt > sess->hb_missed_max) { +- rtrs_err(sess, "HB missed max reached.\n"); +- sess->hb_err_handler(usr_con); ++ if (path->hb_missed_cnt > path->hb_missed_max) { ++ rtrs_err(path, "HB missed max reached.\n"); ++ path->hb_err_handler(usr_con); + return; + } +- if (sess->hb_missed_cnt++) { ++ if (path->hb_missed_cnt++) { + /* Reschedule work without sending hb */ +- schedule_hb(sess); ++ schedule_hb(path); + return; + } + +- sess->hb_last_sent = ktime_get(); ++ path->hb_last_sent = ktime_get(); + + imm = rtrs_to_imm(RTRS_HB_MSG_IMM, 0); +- err = rtrs_post_rdma_write_imm_empty(usr_con, sess->hb_cqe, imm, ++ err = rtrs_post_rdma_write_imm_empty(usr_con, path->hb_cqe, imm, + NULL); + if (err) { +- rtrs_err(sess, "HB send failed, errno: %d\n", err); +- sess->hb_err_handler(usr_con); ++ rtrs_err(path, "HB send failed, errno: %d\n", err); ++ path->hb_err_handler(usr_con); + return; + } + +- schedule_hb(sess); ++ schedule_hb(path); + } + +-void rtrs_init_hb(struct rtrs_sess *sess, struct ib_cqe *cqe, ++void rtrs_init_hb(struct rtrs_path *path, struct ib_cqe *cqe, + unsigned int interval_ms, unsigned int missed_max, + void (*err_handler)(struct rtrs_con *con), + struct workqueue_struct *wq) + { +- sess->hb_cqe = cqe; +- sess->hb_interval_ms = interval_ms; +- sess->hb_err_handler = err_handler; +- sess->hb_wq = wq; +- sess->hb_missed_max = missed_max; +- sess->hb_missed_cnt = 0; +- INIT_DELAYED_WORK(&sess->hb_dwork, hb_work); ++ path->hb_cqe = cqe; ++ path->hb_interval_ms = interval_ms; ++ path->hb_err_handler = err_handler; ++ path->hb_wq = wq; ++ path->hb_missed_max = missed_max; ++ path->hb_missed_cnt = 0; ++ INIT_DELAYED_WORK(&path->hb_dwork, hb_work); + } + EXPORT_SYMBOL_GPL(rtrs_init_hb); + +-void rtrs_start_hb(struct rtrs_sess *sess) ++void rtrs_start_hb(struct rtrs_path *path) + { +- schedule_hb(sess); ++ schedule_hb(path); + } + EXPORT_SYMBOL_GPL(rtrs_start_hb); + +-void rtrs_stop_hb(struct rtrs_sess *sess) ++void rtrs_stop_hb(struct rtrs_path *path) + { +- cancel_delayed_work_sync(&sess->hb_dwork); +- sess->hb_missed_cnt = 0; ++ cancel_delayed_work_sync(&path->hb_dwork); ++ path->hb_missed_cnt = 0; + } + EXPORT_SYMBOL_GPL(rtrs_stop_hb); + +diff --git a/drivers/infiniband/ulp/rtrs/rtrs.h b/drivers/infiniband/ulp/rtrs/rtrs.h +index 859c79685daf3..c529b6d63c9a0 100644 +--- a/drivers/infiniband/ulp/rtrs/rtrs.h ++++ b/drivers/infiniband/ulp/rtrs/rtrs.h +@@ -53,13 +53,13 @@ struct rtrs_clt_ops { + }; + + struct rtrs_clt *rtrs_clt_open(struct rtrs_clt_ops *ops, +- const char *sessname, ++ const char *pathname, + const struct rtrs_addr *paths, + size_t path_cnt, u16 port, + size_t pdu_sz, u8 reconnect_delay_sec, + s16 max_reconnect_attempts, u32 nr_poll_queues); + +-void rtrs_clt_close(struct rtrs_clt *sess); ++void rtrs_clt_close(struct rtrs_clt *clt_path); + + enum wait_type { + RTRS_PERMIT_NOWAIT = 0, +@@ -175,7 +175,8 @@ bool rtrs_srv_resp_rdma(struct rtrs_srv_op *id, int errno); + + void rtrs_srv_set_sess_priv(struct rtrs_srv *sess, void *priv); + +-int rtrs_srv_get_sess_name(struct rtrs_srv *sess, char *sessname, size_t len); ++int rtrs_srv_get_path_name(struct rtrs_srv *sess, char *pathname, ++ size_t len); + + int rtrs_srv_get_queue_depth(struct rtrs_srv *sess); + +diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c +index 3cadf12954172..7b69b0c9e48d9 100644 +--- a/drivers/infiniband/ulp/srpt/ib_srpt.c ++++ b/drivers/infiniband/ulp/srpt/ib_srpt.c +@@ -565,12 +565,9 @@ static int srpt_refresh_port(struct srpt_port *sport) + if (ret) + return ret; + +- sport->port_guid_id.wwn.priv = sport; +- srpt_format_guid(sport->port_guid_id.name, +- sizeof(sport->port_guid_id.name), ++ srpt_format_guid(sport->guid_name, ARRAY_SIZE(sport->guid_name), + &sport->gid.global.interface_id); +- sport->port_gid_id.wwn.priv = sport; +- snprintf(sport->port_gid_id.name, sizeof(sport->port_gid_id.name), ++ snprintf(sport->gid_name, ARRAY_SIZE(sport->gid_name), + "0x%016llx%016llx", + be64_to_cpu(sport->gid.global.subnet_prefix), + be64_to_cpu(sport->gid.global.interface_id)); +@@ -2314,31 +2311,35 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev, + tag_num = ch->rq_size; + tag_size = 1; /* ib_srpt does not use se_sess->sess_cmd_map */ + +- mutex_lock(&sport->port_guid_id.mutex); +- list_for_each_entry(stpg, &sport->port_guid_id.tpg_list, entry) { +- if (!IS_ERR_OR_NULL(ch->sess)) +- break; +- ch->sess = target_setup_session(&stpg->tpg, tag_num, ++ if (sport->guid_id) { ++ mutex_lock(&sport->guid_id->mutex); ++ list_for_each_entry(stpg, &sport->guid_id->tpg_list, entry) { ++ if (!IS_ERR_OR_NULL(ch->sess)) ++ break; ++ ch->sess = target_setup_session(&stpg->tpg, tag_num, + tag_size, TARGET_PROT_NORMAL, + ch->sess_name, ch, NULL); ++ } ++ mutex_unlock(&sport->guid_id->mutex); + } +- mutex_unlock(&sport->port_guid_id.mutex); + +- mutex_lock(&sport->port_gid_id.mutex); +- list_for_each_entry(stpg, &sport->port_gid_id.tpg_list, entry) { +- if (!IS_ERR_OR_NULL(ch->sess)) +- break; +- ch->sess = target_setup_session(&stpg->tpg, tag_num, ++ if (sport->gid_id) { ++ mutex_lock(&sport->gid_id->mutex); ++ list_for_each_entry(stpg, &sport->gid_id->tpg_list, entry) { ++ if (!IS_ERR_OR_NULL(ch->sess)) ++ break; ++ ch->sess = target_setup_session(&stpg->tpg, tag_num, + tag_size, TARGET_PROT_NORMAL, i_port_id, + ch, NULL); +- if (!IS_ERR_OR_NULL(ch->sess)) +- break; +- /* Retry without leading "0x" */ +- ch->sess = target_setup_session(&stpg->tpg, tag_num, ++ if (!IS_ERR_OR_NULL(ch->sess)) ++ break; ++ /* Retry without leading "0x" */ ++ ch->sess = target_setup_session(&stpg->tpg, tag_num, + tag_size, TARGET_PROT_NORMAL, + i_port_id + 2, ch, NULL); ++ } ++ mutex_unlock(&sport->gid_id->mutex); + } +- mutex_unlock(&sport->port_gid_id.mutex); + + if (IS_ERR_OR_NULL(ch->sess)) { + WARN_ON_ONCE(ch->sess == NULL); +@@ -2983,7 +2984,12 @@ static int srpt_release_sport(struct srpt_port *sport) + return 0; + } + +-static struct se_wwn *__srpt_lookup_wwn(const char *name) ++struct port_and_port_id { ++ struct srpt_port *sport; ++ struct srpt_port_id **port_id; ++}; ++ ++static struct port_and_port_id __srpt_lookup_port(const char *name) + { + struct ib_device *dev; + struct srpt_device *sdev; +@@ -2998,25 +3004,38 @@ static struct se_wwn *__srpt_lookup_wwn(const char *name) + for (i = 0; i < dev->phys_port_cnt; i++) { + sport = &sdev->port[i]; + +- if (strcmp(sport->port_guid_id.name, name) == 0) +- return &sport->port_guid_id.wwn; +- if (strcmp(sport->port_gid_id.name, name) == 0) +- return &sport->port_gid_id.wwn; ++ if (strcmp(sport->guid_name, name) == 0) { ++ kref_get(&sdev->refcnt); ++ return (struct port_and_port_id){ ++ sport, &sport->guid_id}; ++ } ++ if (strcmp(sport->gid_name, name) == 0) { ++ kref_get(&sdev->refcnt); ++ return (struct port_and_port_id){ ++ sport, &sport->gid_id}; ++ } + } + } + +- return NULL; ++ return (struct port_and_port_id){}; + } + +-static struct se_wwn *srpt_lookup_wwn(const char *name) ++/** ++ * srpt_lookup_port() - Look up an RDMA port by name ++ * @name: ASCII port name ++ * ++ * Increments the RDMA port reference count if an RDMA port pointer is returned. ++ * The caller must drop that reference count by calling srpt_port_put_ref(). ++ */ ++static struct port_and_port_id srpt_lookup_port(const char *name) + { +- struct se_wwn *wwn; ++ struct port_and_port_id papi; + + spin_lock(&srpt_dev_lock); +- wwn = __srpt_lookup_wwn(name); ++ papi = __srpt_lookup_port(name); + spin_unlock(&srpt_dev_lock); + +- return wwn; ++ return papi; + } + + static void srpt_free_srq(struct srpt_device *sdev) +@@ -3101,6 +3120,18 @@ static int srpt_use_srq(struct srpt_device *sdev, bool use_srq) + return ret; + } + ++static void srpt_free_sdev(struct kref *refcnt) ++{ ++ struct srpt_device *sdev = container_of(refcnt, typeof(*sdev), refcnt); ++ ++ kfree(sdev); ++} ++ ++static void srpt_sdev_put(struct srpt_device *sdev) ++{ ++ kref_put(&sdev->refcnt, srpt_free_sdev); ++} ++ + /** + * srpt_add_one - InfiniBand device addition callback function + * @device: Describes a HCA. +@@ -3119,6 +3150,7 @@ static int srpt_add_one(struct ib_device *device) + if (!sdev) + return -ENOMEM; + ++ kref_init(&sdev->refcnt); + sdev->device = device; + mutex_init(&sdev->sdev_mutex); + +@@ -3182,10 +3214,6 @@ static int srpt_add_one(struct ib_device *device) + sport->port_attrib.srp_sq_size = DEF_SRPT_SQ_SIZE; + sport->port_attrib.use_srq = false; + INIT_WORK(&sport->work, srpt_refresh_port_work); +- mutex_init(&sport->port_guid_id.mutex); +- INIT_LIST_HEAD(&sport->port_guid_id.tpg_list); +- mutex_init(&sport->port_gid_id.mutex); +- INIT_LIST_HEAD(&sport->port_gid_id.tpg_list); + + ret = srpt_refresh_port(sport); + if (ret) { +@@ -3214,7 +3242,7 @@ err_ring: + srpt_free_srq(sdev); + ib_dealloc_pd(sdev->pd); + free_dev: +- kfree(sdev); ++ srpt_sdev_put(sdev); + pr_info("%s(%s) failed.\n", __func__, dev_name(&device->dev)); + return ret; + } +@@ -3258,7 +3286,7 @@ static void srpt_remove_one(struct ib_device *device, void *client_data) + + ib_dealloc_pd(sdev->pd); + +- kfree(sdev); ++ srpt_sdev_put(sdev); + } + + static struct ib_client srpt_client = { +@@ -3286,10 +3314,10 @@ static struct srpt_port_id *srpt_wwn_to_sport_id(struct se_wwn *wwn) + { + struct srpt_port *sport = wwn->priv; + +- if (wwn == &sport->port_guid_id.wwn) +- return &sport->port_guid_id; +- if (wwn == &sport->port_gid_id.wwn) +- return &sport->port_gid_id; ++ if (sport->guid_id && &sport->guid_id->wwn == wwn) ++ return sport->guid_id; ++ if (sport->gid_id && &sport->gid_id->wwn == wwn) ++ return sport->gid_id; + WARN_ON_ONCE(true); + return NULL; + } +@@ -3804,7 +3832,31 @@ static struct se_wwn *srpt_make_tport(struct target_fabric_configfs *tf, + struct config_group *group, + const char *name) + { +- return srpt_lookup_wwn(name) ? : ERR_PTR(-EINVAL); ++ struct port_and_port_id papi = srpt_lookup_port(name); ++ struct srpt_port *sport = papi.sport; ++ struct srpt_port_id *port_id; ++ ++ if (!papi.port_id) ++ return ERR_PTR(-EINVAL); ++ if (*papi.port_id) { ++ /* Attempt to create a directory that already exists. */ ++ WARN_ON_ONCE(true); ++ return &(*papi.port_id)->wwn; ++ } ++ port_id = kzalloc(sizeof(*port_id), GFP_KERNEL); ++ if (!port_id) { ++ srpt_sdev_put(sport->sdev); ++ return ERR_PTR(-ENOMEM); ++ } ++ mutex_init(&port_id->mutex); ++ INIT_LIST_HEAD(&port_id->tpg_list); ++ port_id->wwn.priv = sport; ++ memcpy(port_id->name, port_id == sport->guid_id ? sport->guid_name : ++ sport->gid_name, ARRAY_SIZE(port_id->name)); ++ ++ *papi.port_id = port_id; ++ ++ return &port_id->wwn; + } + + /** +@@ -3813,6 +3865,18 @@ static struct se_wwn *srpt_make_tport(struct target_fabric_configfs *tf, + */ + static void srpt_drop_tport(struct se_wwn *wwn) + { ++ struct srpt_port_id *port_id = container_of(wwn, typeof(*port_id), wwn); ++ struct srpt_port *sport = wwn->priv; ++ ++ if (sport->guid_id == port_id) ++ sport->guid_id = NULL; ++ else if (sport->gid_id == port_id) ++ sport->gid_id = NULL; ++ else ++ WARN_ON_ONCE(true); ++ ++ srpt_sdev_put(sport->sdev); ++ kfree(port_id); + } + + static ssize_t srpt_wwn_version_show(struct config_item *item, char *buf) +diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h +index 76e66f630c17a..4c46b301eea18 100644 +--- a/drivers/infiniband/ulp/srpt/ib_srpt.h ++++ b/drivers/infiniband/ulp/srpt/ib_srpt.h +@@ -376,7 +376,7 @@ struct srpt_tpg { + }; + + /** +- * struct srpt_port_id - information about an RDMA port name ++ * struct srpt_port_id - LIO RDMA port information + * @mutex: Protects @tpg_list changes. + * @tpg_list: TPGs associated with the RDMA port name. + * @wwn: WWN associated with the RDMA port name. +@@ -393,7 +393,7 @@ struct srpt_port_id { + }; + + /** +- * struct srpt_port - information associated by SRPT with a single IB port ++ * struct srpt_port - SRPT RDMA port information + * @sdev: backpointer to the HCA information. + * @mad_agent: per-port management datagram processing information. + * @enabled: Whether or not this target port is enabled. +@@ -402,8 +402,10 @@ struct srpt_port_id { + * @lid: cached value of the port's lid. + * @gid: cached value of the port's gid. + * @work: work structure for refreshing the aforementioned cached values. +- * @port_guid_id: target port GUID +- * @port_gid_id: target port GID ++ * @guid_name: port name in GUID format. ++ * @guid_id: LIO target port information for the port name in GUID format. ++ * @gid_name: port name in GID format. ++ * @gid_id: LIO target port information for the port name in GID format. + * @port_attrib: Port attributes that can be accessed through configfs. + * @refcount: Number of objects associated with this port. + * @freed_channels: Completion that will be signaled once @refcount becomes 0. +@@ -419,8 +421,10 @@ struct srpt_port { + u32 lid; + union ib_gid gid; + struct work_struct work; +- struct srpt_port_id port_guid_id; +- struct srpt_port_id port_gid_id; ++ char guid_name[64]; ++ struct srpt_port_id *guid_id; ++ char gid_name[64]; ++ struct srpt_port_id *gid_id; + struct srpt_port_attrib port_attrib; + atomic_t refcount; + struct completion *freed_channels; +@@ -430,6 +434,7 @@ struct srpt_port { + + /** + * struct srpt_device - information associated by SRPT with a single HCA ++ * @refcnt: Reference count for this device. + * @device: Backpointer to the struct ib_device managed by the IB core. + * @pd: IB protection domain. + * @lkey: L_Key (local key) with write access to all local memory. +@@ -445,6 +450,7 @@ struct srpt_port { + * @port: Information about the ports owned by this HCA. + */ + struct srpt_device { ++ struct kref refcnt; + struct ib_device *device; + struct ib_pd *pd; + u32 lkey; +diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c +index a9065c6ab5508..da2c67cb86422 100644 +--- a/drivers/input/serio/gscps2.c ++++ b/drivers/input/serio/gscps2.c +@@ -350,6 +350,10 @@ static int __init gscps2_probe(struct parisc_device *dev) + ps2port->port = serio; + ps2port->padev = dev; + ps2port->addr = ioremap(hpa, GSC_STATUS + 4); ++ if (!ps2port->addr) { ++ ret = -ENOMEM; ++ goto fail_nomem; ++ } + spin_lock_init(&ps2port->lock); + + gscps2_reset(ps2port); +diff --git a/drivers/interconnect/imx/imx.c b/drivers/interconnect/imx/imx.c +index c770951a909c9..aabd9edf2ef76 100644 +--- a/drivers/interconnect/imx/imx.c ++++ b/drivers/interconnect/imx/imx.c +@@ -226,16 +226,16 @@ int imx_icc_register(struct platform_device *pdev, + struct device *dev = &pdev->dev; + struct icc_onecell_data *data; + struct icc_provider *provider; +- int max_node_id; ++ int num_nodes; + int ret; + + /* icc_onecell_data is indexed by node_id, unlike nodes param */ +- max_node_id = get_max_node_id(nodes, nodes_count); +- data = devm_kzalloc(dev, struct_size(data, nodes, max_node_id), ++ num_nodes = get_max_node_id(nodes, nodes_count) + 1; ++ data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes), + GFP_KERNEL); + if (!data) + return -ENOMEM; +- data->num_nodes = max_node_id; ++ data->num_nodes = num_nodes; + + provider = devm_kzalloc(dev, sizeof(*provider), GFP_KERNEL); + if (!provider) +diff --git a/drivers/iommu/arm/arm-smmu/qcom_iommu.c b/drivers/iommu/arm/arm-smmu/qcom_iommu.c +index b91874cb6cf33..a47cb654b7048 100644 +--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c ++++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c +@@ -748,9 +748,12 @@ static bool qcom_iommu_has_secure_context(struct qcom_iommu_dev *qcom_iommu) + { + struct device_node *child; + +- for_each_child_of_node(qcom_iommu->dev->of_node, child) +- if (of_device_is_compatible(child, "qcom,msm-iommu-v1-sec")) ++ for_each_child_of_node(qcom_iommu->dev->of_node, child) { ++ if (of_device_is_compatible(child, "qcom,msm-iommu-v1-sec")) { ++ of_node_put(child); + return true; ++ } ++ } + + return false; + } +diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c +index 939ffa7689867..f96acc3525e8f 100644 +--- a/drivers/iommu/exynos-iommu.c ++++ b/drivers/iommu/exynos-iommu.c +@@ -630,7 +630,7 @@ static int exynos_sysmmu_probe(struct platform_device *pdev) + + ret = iommu_device_register(&data->iommu, &exynos_iommu_ops, dev); + if (ret) +- return ret; ++ goto err_iommu_register; + + platform_set_drvdata(pdev, data); + +@@ -657,6 +657,10 @@ static int exynos_sysmmu_probe(struct platform_device *pdev) + pm_runtime_enable(dev); + + return 0; ++ ++err_iommu_register: ++ iommu_device_sysfs_remove(&data->iommu); ++ return ret; + } + + static int __maybe_unused exynos_sysmmu_suspend(struct device *dev) +diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c +index 3d9cb711e87b8..f026bd269cb0b 100644 +--- a/drivers/iommu/intel/dmar.c ++++ b/drivers/iommu/intel/dmar.c +@@ -497,7 +497,7 @@ static int dmar_parse_one_rhsa(struct acpi_dmar_header *header, void *arg) + if (drhd->reg_base_addr == rhsa->base_address) { + int node = pxm_to_node(rhsa->proximity_domain); + +- if (!node_online(node)) ++ if (node != NUMA_NO_NODE && !node_online(node)) + node = NUMA_NO_NODE; + drhd->iommu->node = node; + return 0; +diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig +index aca7b595c4c78..ae1b9f59abc57 100644 +--- a/drivers/irqchip/Kconfig ++++ b/drivers/irqchip/Kconfig +@@ -171,7 +171,7 @@ config MADERA_IRQ + config IRQ_MIPS_CPU + bool + select GENERIC_IRQ_CHIP +- select GENERIC_IRQ_IPI if SYS_SUPPORTS_MULTITHREADING ++ select GENERIC_IRQ_IPI if SMP && SYS_SUPPORTS_MULTITHREADING + select IRQ_DOMAIN + select GENERIC_IRQ_EFFECTIVE_AFF_MASK + +@@ -304,7 +304,8 @@ config KEYSTONE_IRQ + + config MIPS_GIC + bool +- select GENERIC_IRQ_IPI ++ select GENERIC_IRQ_IPI if SMP ++ select IRQ_DOMAIN_HIERARCHY + select MIPS_CM + + config INGENIC_IRQ +diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c +index 54c7092cc61d9..d815285f1efe3 100644 +--- a/drivers/irqchip/irq-mips-gic.c ++++ b/drivers/irqchip/irq-mips-gic.c +@@ -51,13 +51,15 @@ static DEFINE_PER_CPU_READ_MOSTLY(unsigned long[GIC_MAX_LONGS], pcpu_masks); + + static DEFINE_SPINLOCK(gic_lock); + static struct irq_domain *gic_irq_domain; +-static struct irq_domain *gic_ipi_domain; + static int gic_shared_intrs; + static unsigned int gic_cpu_pin; + static unsigned int timer_cpu_pin; + static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller; ++ ++#ifdef CONFIG_GENERIC_IRQ_IPI + static DECLARE_BITMAP(ipi_resrv, GIC_MAX_INTRS); + static DECLARE_BITMAP(ipi_available, GIC_MAX_INTRS); ++#endif /* CONFIG_GENERIC_IRQ_IPI */ + + static struct gic_all_vpes_chip_data { + u32 map; +@@ -460,9 +462,11 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq, + u32 map; + + if (hwirq >= GIC_SHARED_HWIRQ_BASE) { ++#ifdef CONFIG_GENERIC_IRQ_IPI + /* verify that shared irqs don't conflict with an IPI irq */ + if (test_bit(GIC_HWIRQ_TO_SHARED(hwirq), ipi_resrv)) + return -EBUSY; ++#endif /* CONFIG_GENERIC_IRQ_IPI */ + + err = irq_domain_set_hwirq_and_chip(d, virq, hwirq, + &gic_level_irq_controller, +@@ -551,6 +555,8 @@ static const struct irq_domain_ops gic_irq_domain_ops = { + .map = gic_irq_domain_map, + }; + ++#ifdef CONFIG_GENERIC_IRQ_IPI ++ + static int gic_ipi_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, + const u32 *intspec, unsigned int intsize, + irq_hw_number_t *out_hwirq, +@@ -654,6 +660,48 @@ static const struct irq_domain_ops gic_ipi_domain_ops = { + .match = gic_ipi_domain_match, + }; + ++static int gic_register_ipi_domain(struct device_node *node) ++{ ++ struct irq_domain *gic_ipi_domain; ++ unsigned int v[2], num_ipis; ++ ++ gic_ipi_domain = irq_domain_add_hierarchy(gic_irq_domain, ++ IRQ_DOMAIN_FLAG_IPI_PER_CPU, ++ GIC_NUM_LOCAL_INTRS + gic_shared_intrs, ++ node, &gic_ipi_domain_ops, NULL); ++ if (!gic_ipi_domain) { ++ pr_err("Failed to add IPI domain"); ++ return -ENXIO; ++ } ++ ++ irq_domain_update_bus_token(gic_ipi_domain, DOMAIN_BUS_IPI); ++ ++ if (node && ++ !of_property_read_u32_array(node, "mti,reserved-ipi-vectors", v, 2)) { ++ bitmap_set(ipi_resrv, v[0], v[1]); ++ } else { ++ /* ++ * Reserve 2 interrupts per possible CPU/VP for use as IPIs, ++ * meeting the requirements of arch/mips SMP. ++ */ ++ num_ipis = 2 * num_possible_cpus(); ++ bitmap_set(ipi_resrv, gic_shared_intrs - num_ipis, num_ipis); ++ } ++ ++ bitmap_copy(ipi_available, ipi_resrv, GIC_MAX_INTRS); ++ ++ return 0; ++} ++ ++#else /* !CONFIG_GENERIC_IRQ_IPI */ ++ ++static inline int gic_register_ipi_domain(struct device_node *node) ++{ ++ return 0; ++} ++ ++#endif /* !CONFIG_GENERIC_IRQ_IPI */ ++ + static int gic_cpu_startup(unsigned int cpu) + { + /* Enable or disable EIC */ +@@ -672,11 +720,12 @@ static int gic_cpu_startup(unsigned int cpu) + static int __init gic_of_init(struct device_node *node, + struct device_node *parent) + { +- unsigned int cpu_vec, i, gicconfig, v[2], num_ipis; ++ unsigned int cpu_vec, i, gicconfig; + unsigned long reserved; + phys_addr_t gic_base; + struct resource res; + size_t gic_len; ++ int ret; + + /* Find the first available CPU vector. */ + i = 0; +@@ -718,6 +767,10 @@ static int __init gic_of_init(struct device_node *node, + } + + mips_gic_base = ioremap(gic_base, gic_len); ++ if (!mips_gic_base) { ++ pr_err("Failed to ioremap gic_base\n"); ++ return -ENOMEM; ++ } + + gicconfig = read_gic_config(); + gic_shared_intrs = gicconfig & GIC_CONFIG_NUMINTERRUPTS; +@@ -765,30 +818,9 @@ static int __init gic_of_init(struct device_node *node, + return -ENXIO; + } + +- gic_ipi_domain = irq_domain_add_hierarchy(gic_irq_domain, +- IRQ_DOMAIN_FLAG_IPI_PER_CPU, +- GIC_NUM_LOCAL_INTRS + gic_shared_intrs, +- node, &gic_ipi_domain_ops, NULL); +- if (!gic_ipi_domain) { +- pr_err("Failed to add IPI domain"); +- return -ENXIO; +- } +- +- irq_domain_update_bus_token(gic_ipi_domain, DOMAIN_BUS_IPI); +- +- if (node && +- !of_property_read_u32_array(node, "mti,reserved-ipi-vectors", v, 2)) { +- bitmap_set(ipi_resrv, v[0], v[1]); +- } else { +- /* +- * Reserve 2 interrupts per possible CPU/VP for use as IPIs, +- * meeting the requirements of arch/mips SMP. +- */ +- num_ipis = 2 * num_possible_cpus(); +- bitmap_set(ipi_resrv, gic_shared_intrs - num_ipis, num_ipis); +- } +- +- bitmap_copy(ipi_available, ipi_resrv, GIC_MAX_INTRS); ++ ret = gic_register_ipi_domain(node); ++ if (ret) ++ return ret; + + board_bind_eic_interrupt = &gic_bind_eic_interrupt; + +diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c +index b0566aabc1867..eba277bb8a1f1 100644 +--- a/drivers/md/dm-raid.c ++++ b/drivers/md/dm-raid.c +@@ -3514,7 +3514,7 @@ static void raid_status(struct dm_target *ti, status_type_t type, + { + struct raid_set *rs = ti->private; + struct mddev *mddev = &rs->md; +- struct r5conf *conf = mddev->private; ++ struct r5conf *conf = rs_is_raid456(rs) ? mddev->private : NULL; + int i, max_nr_stripes = conf ? conf->max_nr_stripes : 0; + unsigned long recovery; + unsigned int raid_param_cnt = 1; /* at least 1 for chunksize */ +@@ -3824,7 +3824,7 @@ static void attempt_restore_of_faulty_devices(struct raid_set *rs) + + memset(cleared_failed_devices, 0, sizeof(cleared_failed_devices)); + +- for (i = 0; i < mddev->raid_disks; i++) { ++ for (i = 0; i < rs->raid_disks; i++) { + r = &rs->dev[i].rdev; + /* HM FIXME: enhance journal device recovery processing */ + if (test_bit(Journal, &r->flags)) +diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c +index c88ed14d49e65..0ada99572b689 100644 +--- a/drivers/md/dm-thin-metadata.c ++++ b/drivers/md/dm-thin-metadata.c +@@ -2073,10 +2073,13 @@ int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd, + dm_sm_threshold_fn fn, + void *context) + { +- int r; ++ int r = -EINVAL; + + pmd_write_lock_in_core(pmd); +- r = dm_sm_register_threshold_callback(pmd->metadata_sm, threshold, fn, context); ++ if (!pmd->fail_io) { ++ r = dm_sm_register_threshold_callback(pmd->metadata_sm, ++ threshold, fn, context); ++ } + pmd_write_unlock(pmd); + + return r; +diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c +index 4c67b77c23c1b..0a85e4cd607c6 100644 +--- a/drivers/md/dm-thin.c ++++ b/drivers/md/dm-thin.c +@@ -3401,8 +3401,10 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv) + calc_metadata_threshold(pt), + metadata_low_callback, + pool); +- if (r) ++ if (r) { ++ ti->error = "Error registering metadata threshold"; + goto out_flags_changed; ++ } + + dm_pool_register_pre_commit_callback(pool->pmd, + metadata_pre_commit_callback, pool); +diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c +index 18320444fb0a9..dfb55fe09ce13 100644 +--- a/drivers/md/dm-writecache.c ++++ b/drivers/md/dm-writecache.c +@@ -22,7 +22,7 @@ + + #define HIGH_WATERMARK 50 + #define LOW_WATERMARK 45 +-#define MAX_WRITEBACK_JOBS 0 ++#define MAX_WRITEBACK_JOBS min(0x10000000 / PAGE_SIZE, totalram_pages() / 16) + #define ENDIO_LATENCY 16 + #define WRITEBACK_LATENCY 64 + #define AUTOCOMMIT_BLOCKS_SSD 65536 +@@ -1328,8 +1328,8 @@ enum wc_map_op { + WC_MAP_ERROR, + }; + +-static enum wc_map_op writecache_map_remap_origin(struct dm_writecache *wc, struct bio *bio, +- struct wc_entry *e) ++static void writecache_map_remap_origin(struct dm_writecache *wc, struct bio *bio, ++ struct wc_entry *e) + { + if (e) { + sector_t next_boundary = +@@ -1337,8 +1337,6 @@ static enum wc_map_op writecache_map_remap_origin(struct dm_writecache *wc, stru + if (next_boundary < bio->bi_iter.bi_size >> SECTOR_SHIFT) + dm_accept_partial_bio(bio, next_boundary); + } +- +- return WC_MAP_REMAP_ORIGIN; + } + + static enum wc_map_op writecache_map_read(struct dm_writecache *wc, struct bio *bio) +@@ -1365,14 +1363,16 @@ read_next_block: + map_op = WC_MAP_REMAP; + } + } else { +- map_op = writecache_map_remap_origin(wc, bio, e); ++ writecache_map_remap_origin(wc, bio, e); ++ wc->stats.reads += (bio->bi_iter.bi_size - wc->block_size) >> wc->block_size_bits; ++ map_op = WC_MAP_REMAP_ORIGIN; + } + + return map_op; + } + +-static enum wc_map_op writecache_bio_copy_ssd(struct dm_writecache *wc, struct bio *bio, +- struct wc_entry *e, bool search_used) ++static void writecache_bio_copy_ssd(struct dm_writecache *wc, struct bio *bio, ++ struct wc_entry *e, bool search_used) + { + unsigned bio_size = wc->block_size; + sector_t start_cache_sec = cache_sector(wc, e); +@@ -1412,14 +1412,15 @@ static enum wc_map_op writecache_bio_copy_ssd(struct dm_writecache *wc, struct b + bio->bi_iter.bi_sector = start_cache_sec; + dm_accept_partial_bio(bio, bio_size >> SECTOR_SHIFT); + ++ wc->stats.writes += bio->bi_iter.bi_size >> wc->block_size_bits; ++ wc->stats.writes_allocate += (bio->bi_iter.bi_size - wc->block_size) >> wc->block_size_bits; ++ + if (unlikely(wc->uncommitted_blocks >= wc->autocommit_blocks)) { + wc->uncommitted_blocks = 0; + queue_work(wc->writeback_wq, &wc->flush_work); + } else { + writecache_schedule_autocommit(wc); + } +- +- return WC_MAP_REMAP; + } + + static enum wc_map_op writecache_map_write(struct dm_writecache *wc, struct bio *bio) +@@ -1429,9 +1430,10 @@ static enum wc_map_op writecache_map_write(struct dm_writecache *wc, struct bio + do { + bool found_entry = false; + bool search_used = false; +- wc->stats.writes++; +- if (writecache_has_error(wc)) ++ if (writecache_has_error(wc)) { ++ wc->stats.writes += bio->bi_iter.bi_size >> wc->block_size_bits; + return WC_MAP_ERROR; ++ } + e = writecache_find_entry(wc, bio->bi_iter.bi_sector, 0); + if (e) { + if (!writecache_entry_is_committed(wc, e)) { +@@ -1455,9 +1457,11 @@ static enum wc_map_op writecache_map_write(struct dm_writecache *wc, struct bio + if (unlikely(!e)) { + if (!WC_MODE_PMEM(wc) && !found_entry) { + direct_write: +- wc->stats.writes_around++; + e = writecache_find_entry(wc, bio->bi_iter.bi_sector, WFE_RETURN_FOLLOWING); +- return writecache_map_remap_origin(wc, bio, e); ++ writecache_map_remap_origin(wc, bio, e); ++ wc->stats.writes_around += bio->bi_iter.bi_size >> wc->block_size_bits; ++ wc->stats.writes += bio->bi_iter.bi_size >> wc->block_size_bits; ++ return WC_MAP_REMAP_ORIGIN; + } + wc->stats.writes_blocked_on_freelist++; + writecache_wait_on_freelist(wc); +@@ -1468,10 +1472,13 @@ direct_write: + wc->uncommitted_blocks++; + wc->stats.writes_allocate++; + bio_copy: +- if (WC_MODE_PMEM(wc)) ++ if (WC_MODE_PMEM(wc)) { + bio_copy_block(wc, bio, memory_data(wc, e)); +- else +- return writecache_bio_copy_ssd(wc, bio, e, search_used); ++ wc->stats.writes++; ++ } else { ++ writecache_bio_copy_ssd(wc, bio, e, search_used); ++ return WC_MAP_REMAP; ++ } + } while (bio->bi_iter.bi_size); + + if (unlikely(bio->bi_opf & REQ_FUA || wc->uncommitted_blocks >= wc->autocommit_blocks)) +@@ -1506,7 +1513,7 @@ static enum wc_map_op writecache_map_flush(struct dm_writecache *wc, struct bio + + static enum wc_map_op writecache_map_discard(struct dm_writecache *wc, struct bio *bio) + { +- wc->stats.discards++; ++ wc->stats.discards += bio->bi_iter.bi_size >> wc->block_size_bits; + + if (writecache_has_error(wc)) + return WC_MAP_ERROR; +diff --git a/drivers/md/dm.c b/drivers/md/dm.c +index 36449422e7e07..41d2e1285c077 100644 +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -2911,6 +2911,11 @@ static int dm_call_pr(struct block_device *bdev, iterate_devices_callout_fn fn, + goto out; + ti = dm_table_get_target(table, 0); + ++ if (dm_suspended_md(md)) { ++ ret = -EAGAIN; ++ goto out; ++ } ++ + ret = -EINVAL; + if (!ti->type->iterate_devices) + goto out; +diff --git a/drivers/md/md.c b/drivers/md/md.c +index bf1c5c0e472e3..4bfaf7d4977dd 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -6251,11 +6251,11 @@ static void mddev_detach(struct mddev *mddev) + static void __md_stop(struct mddev *mddev) + { + struct md_personality *pers = mddev->pers; +- md_bitmap_destroy(mddev); + mddev_detach(mddev); + /* Ensure ->event_work is done */ + if (mddev->event_work.func) + flush_workqueue(md_misc_wq); ++ md_bitmap_destroy(mddev); + spin_lock(&mddev->lock); + mddev->pers = NULL; + spin_unlock(&mddev->lock); +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index aa2636582841e..c4c1a3a7d7abc 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -2139,9 +2139,12 @@ static int raid10_remove_disk(struct mddev *mddev, struct md_rdev *rdev) + int err = 0; + int number = rdev->raid_disk; + struct md_rdev **rdevp; +- struct raid10_info *p = conf->mirrors + number; ++ struct raid10_info *p; + + print_conf(conf); ++ if (unlikely(number >= mddev->raid_disks)) ++ return 0; ++ p = conf->mirrors + number; + if (rdev == p->rdev) + rdevp = &p->rdev; + else if (rdev == p->replacement) +diff --git a/drivers/media/pci/tw686x/tw686x-core.c b/drivers/media/pci/tw686x/tw686x-core.c +index 6676e069b515d..384d38754a4b1 100644 +--- a/drivers/media/pci/tw686x/tw686x-core.c ++++ b/drivers/media/pci/tw686x/tw686x-core.c +@@ -315,13 +315,6 @@ static int tw686x_probe(struct pci_dev *pci_dev, + + spin_lock_init(&dev->lock); + +- err = request_irq(pci_dev->irq, tw686x_irq, IRQF_SHARED, +- dev->name, dev); +- if (err < 0) { +- dev_err(&pci_dev->dev, "unable to request interrupt\n"); +- goto iounmap; +- } +- + timer_setup(&dev->dma_delay_timer, tw686x_dma_delay, 0); + + /* +@@ -333,18 +326,23 @@ static int tw686x_probe(struct pci_dev *pci_dev, + err = tw686x_video_init(dev); + if (err) { + dev_err(&pci_dev->dev, "can't register video\n"); +- goto free_irq; ++ goto iounmap; + } + + err = tw686x_audio_init(dev); + if (err) + dev_warn(&pci_dev->dev, "can't register audio\n"); + ++ err = request_irq(pci_dev->irq, tw686x_irq, IRQF_SHARED, ++ dev->name, dev); ++ if (err < 0) { ++ dev_err(&pci_dev->dev, "unable to request interrupt\n"); ++ goto iounmap; ++ } ++ + pci_set_drvdata(pci_dev, dev); + return 0; + +-free_irq: +- free_irq(pci_dev->irq, dev); + iounmap: + pci_iounmap(pci_dev, dev->mmio); + free_region: +diff --git a/drivers/media/pci/tw686x/tw686x-video.c b/drivers/media/pci/tw686x/tw686x-video.c +index b227e9e78ebd0..37a20fe24241f 100644 +--- a/drivers/media/pci/tw686x/tw686x-video.c ++++ b/drivers/media/pci/tw686x/tw686x-video.c +@@ -1282,8 +1282,10 @@ int tw686x_video_init(struct tw686x_dev *dev) + video_set_drvdata(vdev, vc); + + err = video_register_device(vdev, VFL_TYPE_VIDEO, -1); +- if (err < 0) ++ if (err < 0) { ++ video_device_release(vdev); + goto error; ++ } + vc->num = vdev->num; + } + +diff --git a/drivers/media/platform/atmel/atmel-sama7g5-isc.c b/drivers/media/platform/atmel/atmel-sama7g5-isc.c +index 6a5d3f7ce75e5..a4defc30cf412 100644 +--- a/drivers/media/platform/atmel/atmel-sama7g5-isc.c ++++ b/drivers/media/platform/atmel/atmel-sama7g5-isc.c +@@ -587,11 +587,13 @@ static const struct dev_pm_ops microchip_xisc_dev_pm_ops = { + SET_RUNTIME_PM_OPS(xisc_runtime_suspend, xisc_runtime_resume, NULL) + }; + ++#if IS_ENABLED(CONFIG_OF) + static const struct of_device_id microchip_xisc_of_match[] = { + { .compatible = "microchip,sama7g5-isc" }, + { } + }; + MODULE_DEVICE_TABLE(of, microchip_xisc_of_match); ++#endif + + static struct platform_driver microchip_xisc_driver = { + .probe = microchip_xisc_probe, +diff --git a/drivers/media/platform/imx-jpeg/mxc-jpeg-hw.c b/drivers/media/platform/imx-jpeg/mxc-jpeg-hw.c +index 29c604b1b1790..718b7b08f93e0 100644 +--- a/drivers/media/platform/imx-jpeg/mxc-jpeg-hw.c ++++ b/drivers/media/platform/imx-jpeg/mxc-jpeg-hw.c +@@ -79,6 +79,11 @@ void mxc_jpeg_enable_irq(void __iomem *reg, int slot) + writel(0xFFFFFFFF, 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)); ++} ++ + void mxc_jpeg_sw_reset(void __iomem *reg) + { + /* +diff --git a/drivers/media/platform/imx-jpeg/mxc-jpeg-hw.h b/drivers/media/platform/imx-jpeg/mxc-jpeg-hw.h +index ae70d3a0dc243..bf4e1973a0661 100644 +--- a/drivers/media/platform/imx-jpeg/mxc-jpeg-hw.h ++++ b/drivers/media/platform/imx-jpeg/mxc-jpeg-hw.h +@@ -53,10 +53,10 @@ + #define CAST_REC_REGS_SEL CAST_STATUS4 + #define CAST_LUMTH CAST_STATUS5 + #define CAST_CHRTH CAST_STATUS6 +-#define CAST_NOMFRSIZE_LO CAST_STATUS7 +-#define CAST_NOMFRSIZE_HI CAST_STATUS8 +-#define CAST_OFBSIZE_LO CAST_STATUS9 +-#define CAST_OFBSIZE_HI CAST_STATUS10 ++#define CAST_NOMFRSIZE_LO CAST_STATUS16 ++#define CAST_NOMFRSIZE_HI CAST_STATUS17 ++#define CAST_OFBSIZE_LO CAST_STATUS18 ++#define CAST_OFBSIZE_HI CAST_STATUS19 + + #define MXC_MAX_SLOTS 1 /* TODO use all 4 slots*/ + /* JPEG-Decoder Wrapper Slot Registers 0..3 */ +@@ -125,6 +125,7 @@ u32 mxc_jpeg_get_offset(void __iomem *reg, int slot); + void mxc_jpeg_enable_slot(void __iomem *reg, int slot); + void mxc_jpeg_set_l_endian(void __iomem *reg, int le); + void mxc_jpeg_enable_irq(void __iomem *reg, int slot); ++void mxc_jpeg_disable_irq(void __iomem *reg, int slot); + int mxc_jpeg_set_input(void __iomem *reg, u32 in_buf, u32 bufsize); + int mxc_jpeg_set_output(void __iomem *reg, u16 out_pitch, u32 out_buf, + u16 w, u16 h); +diff --git a/drivers/media/platform/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/imx-jpeg/mxc-jpeg.c +index 37905547466bd..984fcdfa0f098 100644 +--- a/drivers/media/platform/imx-jpeg/mxc-jpeg.c ++++ b/drivers/media/platform/imx-jpeg/mxc-jpeg.c +@@ -49,6 +49,7 @@ + #include <linux/slab.h> + #include <linux/irqreturn.h> + #include <linux/interrupt.h> ++#include <linux/pm_runtime.h> + #include <linux/pm_domain.h> + #include <linux/string.h> + +@@ -81,6 +82,7 @@ static const struct mxc_jpeg_fmt mxc_formats[] = { + .h_align = 3, + .v_align = 3, + .flags = MXC_JPEG_FMT_TYPE_RAW, ++ .precision = 8, + }, + { + .name = "ARGB", /* ARGBARGB packed format */ +@@ -92,10 +94,11 @@ static const struct mxc_jpeg_fmt mxc_formats[] = { + .h_align = 3, + .v_align = 3, + .flags = MXC_JPEG_FMT_TYPE_RAW, ++ .precision = 8, + }, + { + .name = "YUV420", /* 1st plane = Y, 2nd plane = UV */ +- .fourcc = V4L2_PIX_FMT_NV12, ++ .fourcc = V4L2_PIX_FMT_NV12M, + .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, + .nc = 3, + .depth = 12, /* 6 bytes (4Y + UV) for 4 pixels */ +@@ -103,6 +106,7 @@ static const struct mxc_jpeg_fmt mxc_formats[] = { + .h_align = 4, + .v_align = 4, + .flags = MXC_JPEG_FMT_TYPE_RAW, ++ .precision = 8, + }, + { + .name = "YUV422", /* YUYV */ +@@ -114,6 +118,7 @@ static const struct mxc_jpeg_fmt mxc_formats[] = { + .h_align = 4, + .v_align = 3, + .flags = MXC_JPEG_FMT_TYPE_RAW, ++ .precision = 8, + }, + { + .name = "YUV444", /* YUVYUV */ +@@ -125,6 +130,7 @@ static const struct mxc_jpeg_fmt mxc_formats[] = { + .h_align = 3, + .v_align = 3, + .flags = MXC_JPEG_FMT_TYPE_RAW, ++ .precision = 8, + }, + { + .name = "Gray", /* Gray (Y8/Y12) or Single Comp */ +@@ -136,6 +142,7 @@ static const struct mxc_jpeg_fmt mxc_formats[] = { + .h_align = 3, + .v_align = 3, + .flags = MXC_JPEG_FMT_TYPE_RAW, ++ .precision = 8, + }, + }; + +@@ -294,6 +301,9 @@ struct mxc_jpeg_src_buf { + /* mxc-jpeg specific */ + bool dht_needed; + bool jpeg_parse_error; ++ const struct mxc_jpeg_fmt *fmt; ++ int w; ++ int h; + }; + + static inline struct mxc_jpeg_src_buf *vb2_to_mxc_buf(struct vb2_buffer *vb) +@@ -306,6 +316,9 @@ static unsigned int debug; + module_param(debug, int, 0644); + MODULE_PARM_DESC(debug, "Debug level (0-3)"); + ++static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q, u32 precision); ++static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q); ++ + static void _bswap16(u16 *a) + { + *a = ((*a & 0x00FF) << 8) | ((*a & 0xFF00) >> 8); +@@ -389,7 +402,7 @@ static enum mxc_jpeg_image_format mxc_jpeg_fourcc_to_imgfmt(u32 fourcc) + return MXC_JPEG_GRAY; + case V4L2_PIX_FMT_YUYV: + return MXC_JPEG_YUV422; +- case V4L2_PIX_FMT_NV12: ++ case V4L2_PIX_FMT_NV12M: + return MXC_JPEG_YUV420; + case V4L2_PIX_FMT_YUV24: + return MXC_JPEG_YUV444; +@@ -493,6 +506,7 @@ static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg, + GFP_ATOMIC); + if (!cfg_stm) + goto err; ++ memset(cfg_stm, 0, MXC_JPEG_MAX_CFG_STREAM); + jpeg->slot_data[slot].cfg_stream_vaddr = cfg_stm; + + skip_alloc: +@@ -531,6 +545,18 @@ static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg, + jpeg->slot_data[slot].used = false; + } + ++static void mxc_jpeg_check_and_set_last_buffer(struct mxc_jpeg_ctx *ctx, ++ struct vb2_v4l2_buffer *src_buf, ++ struct vb2_v4l2_buffer *dst_buf) ++{ ++ if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx, src_buf)) { ++ dst_buf->flags |= V4L2_BUF_FLAG_LAST; ++ v4l2_m2m_mark_stopped(ctx->fh.m2m_ctx); ++ notify_eos(ctx); ++ ctx->header_parsed = false; ++ } ++} ++ + static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv) + { + struct mxc_jpeg_dev *jpeg = priv; +@@ -553,15 +579,8 @@ static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv) + dev_dbg(dev, "Irq %d on slot %d.\n", irq, slot); + + ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); +- if (!ctx) { +- dev_err(dev, +- "Instance released before the end of transaction.\n"); +- /* soft reset only resets internal state, not registers */ +- mxc_jpeg_sw_reset(reg); +- /* clear all interrupts */ +- writel(0xFFFFFFFF, reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS)); ++ if (WARN_ON(!ctx)) + goto job_unlock; +- } + + if (slot != ctx->slot) { + /* TODO investigate when adding multi-instance support */ +@@ -605,6 +624,7 @@ static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv) + dev_dbg(dev, "Decoder DHT cfg finished. Start decoding...\n"); + goto job_unlock; + } ++ + if (jpeg->mode == MXC_JPEG_ENCODE) { + payload = readl(reg + MXC_SLOT_OFFSET(slot, SLOT_BUF_PTR)); + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload); +@@ -632,7 +652,9 @@ static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv) + buf_state = VB2_BUF_STATE_DONE; + + buffers_done: ++ mxc_jpeg_disable_irq(reg, ctx->slot); + jpeg->slot_data[slot].used = false; /* unused, but don't free */ ++ mxc_jpeg_check_and_set_last_buffer(ctx, src_buf, dst_buf); + v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + v4l2_m2m_buf_done(src_buf, buf_state); +@@ -658,7 +680,7 @@ static int mxc_jpeg_fixup_sof(struct mxc_jpeg_sof *sof, + _bswap16(&sof->width); + + switch (fourcc) { +- case V4L2_PIX_FMT_NV12: ++ case V4L2_PIX_FMT_NV12M: + sof->components_no = 3; + sof->comp[0].v = 0x2; + sof->comp[0].h = 0x2; +@@ -694,7 +716,7 @@ static int mxc_jpeg_fixup_sos(struct mxc_jpeg_sos *sos, + u8 *sof_u8 = (u8 *)sos; + + switch (fourcc) { +- case V4L2_PIX_FMT_NV12: ++ case V4L2_PIX_FMT_NV12M: + sos->components_no = 3; + break; + case V4L2_PIX_FMT_YUYV: +@@ -728,7 +750,13 @@ static unsigned int mxc_jpeg_setup_cfg_stream(void *cfg_stream_vaddr, + u32 fourcc, + u16 w, u16 h) + { +- unsigned int offset = 0; ++ /* ++ * There is a hardware issue that first 128 bytes of configuration data ++ * can't be loaded correctly. ++ * To avoid this issue, we need to write the configuration from ++ * an offset which should be no less than 0x80 (128 bytes). ++ */ ++ unsigned int offset = 0x80; + u8 *cfg = (u8 *)cfg_stream_vaddr; + struct mxc_jpeg_sof *sof; + struct mxc_jpeg_sos *sos; +@@ -855,8 +883,8 @@ static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf, + jpeg->slot_data[slot].cfg_stream_size = + mxc_jpeg_setup_cfg_stream(cfg_stream_vaddr, + q_data->fmt->fourcc, +- q_data->w_adjusted, +- q_data->h_adjusted); ++ q_data->w, ++ q_data->h); + + /* chain the config descriptor with the encoding descriptor */ + cfg_desc->next_descpt_ptr = desc_handle | MXC_NXT_DESCPT_EN; +@@ -894,6 +922,67 @@ static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf, + mxc_jpeg_set_desc(cfg_desc_handle, reg, slot); + } + ++static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx, ++ struct mxc_jpeg_src_buf *jpeg_src_buf) ++{ ++ struct device *dev = ctx->mxc_jpeg->dev; ++ struct mxc_jpeg_q_data *q_data_cap; ++ ++ if (!jpeg_src_buf->fmt) ++ return false; ++ ++ q_data_cap = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ if (q_data_cap->fmt != jpeg_src_buf->fmt || ++ q_data_cap->w != jpeg_src_buf->w || ++ q_data_cap->h != jpeg_src_buf->h) { ++ dev_dbg(dev, "Detected jpeg res=(%dx%d)->(%dx%d), pixfmt=%c%c%c%c\n", ++ q_data_cap->w, q_data_cap->h, ++ jpeg_src_buf->w, jpeg_src_buf->h, ++ (jpeg_src_buf->fmt->fourcc & 0xff), ++ (jpeg_src_buf->fmt->fourcc >> 8) & 0xff, ++ (jpeg_src_buf->fmt->fourcc >> 16) & 0xff, ++ (jpeg_src_buf->fmt->fourcc >> 24) & 0xff); ++ ++ /* ++ * set-up the capture queue with the pixelformat and resolution ++ * detected from the jpeg output stream ++ */ ++ q_data_cap->w = jpeg_src_buf->w; ++ q_data_cap->h = jpeg_src_buf->h; ++ q_data_cap->fmt = jpeg_src_buf->fmt; ++ q_data_cap->w_adjusted = q_data_cap->w; ++ q_data_cap->h_adjusted = q_data_cap->h; ++ ++ /* ++ * align up the resolution for CAST IP, ++ * but leave the buffer resolution unchanged ++ */ ++ v4l_bound_align_image(&q_data_cap->w_adjusted, ++ q_data_cap->w_adjusted, /* adjust up */ ++ MXC_JPEG_MAX_WIDTH, ++ q_data_cap->fmt->h_align, ++ &q_data_cap->h_adjusted, ++ q_data_cap->h_adjusted, /* adjust up */ ++ MXC_JPEG_MAX_HEIGHT, ++ 0, ++ 0); ++ ++ /* setup bytesperline/sizeimage for capture queue */ ++ mxc_jpeg_bytesperline(q_data_cap, jpeg_src_buf->fmt->precision); ++ mxc_jpeg_sizeimage(q_data_cap); ++ notify_src_chg(ctx); ++ ctx->source_change = 1; ++ } ++ return ctx->source_change ? true : false; ++} ++ ++static int mxc_jpeg_job_ready(void *priv) ++{ ++ struct mxc_jpeg_ctx *ctx = priv; ++ ++ return ctx->source_change ? 0 : 1; ++} ++ + static void mxc_jpeg_device_run(void *priv) + { + struct mxc_jpeg_ctx *ctx = priv; +@@ -932,6 +1021,7 @@ static void mxc_jpeg_device_run(void *priv) + jpeg_src_buf->jpeg_parse_error = true; + } + if (jpeg_src_buf->jpeg_parse_error) { ++ mxc_jpeg_check_and_set_last_buffer(ctx, src_buf, dst_buf); + v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); +@@ -941,6 +1031,13 @@ static void mxc_jpeg_device_run(void *priv) + + return; + } ++ if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE) { ++ if (ctx->source_change || mxc_jpeg_source_change(ctx, jpeg_src_buf)) { ++ spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags); ++ v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); ++ return; ++ } ++ } + + /* + * TODO: this reset should be removed, once we figure out +@@ -985,24 +1082,28 @@ static int mxc_jpeg_decoder_cmd(struct file *file, void *priv, + { + struct v4l2_fh *fh = file->private_data; + struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); +- struct device *dev = ctx->mxc_jpeg->dev; + int ret; + + ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, cmd); + if (ret < 0) + return ret; + +- if (cmd->cmd == V4L2_DEC_CMD_STOP) { +- dev_dbg(dev, "Received V4L2_DEC_CMD_STOP"); +- if (v4l2_m2m_num_src_bufs_ready(fh->m2m_ctx) == 0) { +- /* No more src bufs, notify app EOS */ +- notify_eos(ctx); +- } else { +- /* will send EOS later*/ +- ctx->stopping = 1; +- } ++ if (!vb2_is_streaming(v4l2_m2m_get_src_vq(fh->m2m_ctx))) ++ return 0; ++ ++ ret = v4l2_m2m_ioctl_decoder_cmd(file, priv, cmd); ++ if (ret < 0) ++ return ret; ++ ++ if (cmd->cmd == V4L2_DEC_CMD_STOP && ++ v4l2_m2m_has_stopped(fh->m2m_ctx)) { ++ notify_eos(ctx); ++ ctx->header_parsed = false; + } + ++ if (cmd->cmd == V4L2_DEC_CMD_START && ++ v4l2_m2m_has_stopped(fh->m2m_ctx)) ++ vb2_clear_last_buffer_dequeued(&fh->m2m_ctx->cap_q_ctx.q); + return 0; + } + +@@ -1011,23 +1112,27 @@ static int mxc_jpeg_encoder_cmd(struct file *file, void *priv, + { + struct v4l2_fh *fh = file->private_data; + struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); +- struct device *dev = ctx->mxc_jpeg->dev; + int ret; + + ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, cmd); + if (ret < 0) + return ret; + +- if (cmd->cmd == V4L2_ENC_CMD_STOP) { +- dev_dbg(dev, "Received V4L2_ENC_CMD_STOP"); +- if (v4l2_m2m_num_src_bufs_ready(fh->m2m_ctx) == 0) { +- /* No more src bufs, notify app EOS */ +- notify_eos(ctx); +- } else { +- /* will send EOS later*/ +- ctx->stopping = 1; +- } +- } ++ if (!vb2_is_streaming(v4l2_m2m_get_src_vq(fh->m2m_ctx)) || ++ !vb2_is_streaming(v4l2_m2m_get_dst_vq(fh->m2m_ctx))) ++ return 0; ++ ++ ret = v4l2_m2m_ioctl_encoder_cmd(file, fh, cmd); ++ if (ret < 0) ++ return 0; ++ ++ if (cmd->cmd == V4L2_ENC_CMD_STOP && ++ v4l2_m2m_has_stopped(fh->m2m_ctx)) ++ notify_eos(ctx); ++ ++ if (cmd->cmd == V4L2_ENC_CMD_START && ++ v4l2_m2m_has_stopped(fh->m2m_ctx)) ++ vb2_clear_last_buffer_dequeued(&fh->m2m_ctx->cap_q_ctx.q); + + return 0; + } +@@ -1040,16 +1145,28 @@ static int mxc_jpeg_queue_setup(struct vb2_queue *q, + { + struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q); + struct mxc_jpeg_q_data *q_data = NULL; ++ struct mxc_jpeg_q_data tmp_q; + int i; + + q_data = mxc_jpeg_get_q_data(ctx, q->type); + if (!q_data) + return -EINVAL; + ++ tmp_q.fmt = q_data->fmt; ++ tmp_q.w = q_data->w_adjusted; ++ tmp_q.h = q_data->h_adjusted; ++ for (i = 0; i < MXC_JPEG_MAX_PLANES; i++) { ++ tmp_q.bytesperline[i] = q_data->bytesperline[i]; ++ tmp_q.sizeimage[i] = q_data->sizeimage[i]; ++ } ++ mxc_jpeg_sizeimage(&tmp_q); ++ for (i = 0; i < MXC_JPEG_MAX_PLANES; i++) ++ tmp_q.sizeimage[i] = max(tmp_q.sizeimage[i], q_data->sizeimage[i]); ++ + /* Handle CREATE_BUFS situation - *nplanes != 0 */ + if (*nplanes) { + for (i = 0; i < *nplanes; i++) { +- if (sizes[i] < q_data->sizeimage[i]) ++ if (sizes[i] < tmp_q.sizeimage[i]) + return -EINVAL; + } + return 0; +@@ -1058,7 +1175,7 @@ static int mxc_jpeg_queue_setup(struct vb2_queue *q, + /* Handle REQBUFS situation */ + *nplanes = q_data->fmt->colplanes; + for (i = 0; i < *nplanes; i++) +- sizes[i] = q_data->sizeimage[i]; ++ sizes[i] = tmp_q.sizeimage[i]; + + return 0; + } +@@ -1067,10 +1184,21 @@ static int mxc_jpeg_start_streaming(struct vb2_queue *q, unsigned int count) + { + struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q); + struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, q->type); ++ int ret; ++ ++ v4l2_m2m_update_start_streaming_state(ctx->fh.m2m_ctx, q); + ++ if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE && V4L2_TYPE_IS_CAPTURE(q->type)) ++ ctx->source_change = 0; + dev_dbg(ctx->mxc_jpeg->dev, "Start streaming ctx=%p", ctx); + q_data->sequence = 0; + ++ ret = pm_runtime_resume_and_get(ctx->mxc_jpeg->dev); ++ if (ret < 0) { ++ dev_err(ctx->mxc_jpeg->dev, "Failed to power up jpeg\n"); ++ return ret; ++ } ++ + return 0; + } + +@@ -1088,9 +1216,18 @@ static void mxc_jpeg_stop_streaming(struct vb2_queue *q) + else + vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + if (!vbuf) +- return; ++ break; + v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); + } ++ ++ v4l2_m2m_update_stop_streaming_state(ctx->fh.m2m_ctx, q); ++ if (V4L2_TYPE_IS_OUTPUT(q->type) && ++ v4l2_m2m_has_stopped(ctx->fh.m2m_ctx)) { ++ notify_eos(ctx); ++ ctx->header_parsed = false; ++ } ++ ++ pm_runtime_put_sync(&ctx->mxc_jpeg->pdev->dev); + } + + static int mxc_jpeg_valid_comp_id(struct device *dev, +@@ -1130,14 +1267,17 @@ static u32 mxc_jpeg_get_image_format(struct device *dev, + + for (i = 0; i < MXC_JPEG_NUM_FORMATS; i++) + if (mxc_formats[i].subsampling == header->frame.subsampling && +- mxc_formats[i].nc == header->frame.num_components) { ++ mxc_formats[i].nc == header->frame.num_components && ++ mxc_formats[i].precision == header->frame.precision) { + fourcc = mxc_formats[i].fourcc; + break; + } + if (fourcc == 0) { +- dev_err(dev, "Could not identify image format nc=%d, subsampling=%d\n", ++ dev_err(dev, ++ "Could not identify image format nc=%d, subsampling=%d, precision=%d\n", + header->frame.num_components, +- header->frame.subsampling); ++ header->frame.subsampling, ++ header->frame.precision); + return fourcc; + } + /* +@@ -1155,26 +1295,29 @@ static u32 mxc_jpeg_get_image_format(struct device *dev, + return fourcc; + } + +-static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q, +- u32 precision) ++static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q, u32 precision) + { + /* Bytes distance between the leftmost pixels in two adjacent lines */ + if (q->fmt->fourcc == V4L2_PIX_FMT_JPEG) { + /* bytesperline unused for compressed formats */ + q->bytesperline[0] = 0; + q->bytesperline[1] = 0; +- } else if (q->fmt->fourcc == V4L2_PIX_FMT_NV12) { ++ } else if (q->fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_420) { + /* When the image format is planar the bytesperline value + * applies to the first plane and is divided by the same factor + * as the width field for the other planes + */ +- q->bytesperline[0] = q->w * (precision / 8) * +- (q->fmt->depth / 8); ++ q->bytesperline[0] = q->w * DIV_ROUND_UP(precision, 8); + q->bytesperline[1] = q->bytesperline[0]; ++ } else if (q->fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_422) { ++ q->bytesperline[0] = q->w * DIV_ROUND_UP(precision, 8) * 2; ++ q->bytesperline[1] = 0; ++ } else if (q->fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_444) { ++ q->bytesperline[0] = q->w * DIV_ROUND_UP(precision, 8) * q->fmt->nc; ++ q->bytesperline[1] = 0; + } else { +- /* single plane formats */ +- q->bytesperline[0] = q->w * (precision / 8) * +- (q->fmt->depth / 8); ++ /* grayscale */ ++ q->bytesperline[0] = q->w * DIV_ROUND_UP(precision, 8); + q->bytesperline[1] = 0; + } + } +@@ -1195,22 +1338,22 @@ static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q) + } else { + q->sizeimage[0] = q->bytesperline[0] * q->h; + q->sizeimage[1] = 0; +- if (q->fmt->fourcc == V4L2_PIX_FMT_NV12) ++ if (q->fmt->fourcc == V4L2_PIX_FMT_NV12M) + q->sizeimage[1] = q->sizeimage[0] / 2; + } + } + +-static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, +- u8 *src_addr, u32 size, bool *dht_needed) ++static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb) + { + struct device *dev = ctx->mxc_jpeg->dev; +- struct mxc_jpeg_q_data *q_data_out, *q_data_cap; +- enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; +- bool src_chg = false; ++ struct mxc_jpeg_q_data *q_data_out; + u32 fourcc; + struct v4l2_jpeg_header header; + struct mxc_jpeg_sof *psof = NULL; + struct mxc_jpeg_sos *psos = NULL; ++ struct mxc_jpeg_src_buf *jpeg_src_buf = vb2_to_mxc_buf(vb); ++ u8 *src_addr = (u8 *)vb2_plane_vaddr(vb, 0); ++ u32 size = vb2_get_plane_payload(vb, 0); + int ret; + + memset(&header, 0, sizeof(header)); +@@ -1221,7 +1364,7 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, + } + + /* if DHT marker present, no need to inject default one */ +- *dht_needed = (header.num_dht == 0); ++ jpeg_src_buf->dht_needed = (header.num_dht == 0); + + q_data_out = mxc_jpeg_get_q_data(ctx, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); +@@ -1229,21 +1372,15 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, + dev_warn(dev, "Invalid user resolution 0x0"); + dev_warn(dev, "Keeping resolution from JPEG: %dx%d", + header.frame.width, header.frame.height); +- q_data_out->w = header.frame.width; +- q_data_out->h = header.frame.height; + } else if (header.frame.width != q_data_out->w || + header.frame.height != q_data_out->h) { + dev_err(dev, + "Resolution mismatch: %dx%d (JPEG) versus %dx%d(user)", + header.frame.width, header.frame.height, + q_data_out->w, q_data_out->h); +- return -EINVAL; +- } +- if (header.frame.width % 8 != 0 || header.frame.height % 8 != 0) { +- dev_err(dev, "JPEG width or height not multiple of 8: %dx%d\n", +- header.frame.width, header.frame.height); +- return -EINVAL; + } ++ q_data_out->w = header.frame.width; ++ q_data_out->h = header.frame.height; + if (header.frame.width > MXC_JPEG_MAX_WIDTH || + header.frame.height > MXC_JPEG_MAX_HEIGHT) { + dev_err(dev, "JPEG width or height should be <= 8192: %dx%d\n", +@@ -1271,51 +1408,13 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, + if (fourcc == 0) + return -EINVAL; + +- /* +- * set-up the capture queue with the pixelformat and resolution +- * detected from the jpeg output stream +- */ +- q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type); +- if (q_data_cap->w != header.frame.width || +- q_data_cap->h != header.frame.height) +- src_chg = true; +- q_data_cap->w = header.frame.width; +- q_data_cap->h = header.frame.height; +- q_data_cap->fmt = mxc_jpeg_find_format(ctx, fourcc); +- q_data_cap->w_adjusted = q_data_cap->w; +- q_data_cap->h_adjusted = q_data_cap->h; +- /* +- * align up the resolution for CAST IP, +- * but leave the buffer resolution unchanged +- */ +- v4l_bound_align_image(&q_data_cap->w_adjusted, +- q_data_cap->w_adjusted, /* adjust up */ +- MXC_JPEG_MAX_WIDTH, +- q_data_cap->fmt->h_align, +- &q_data_cap->h_adjusted, +- q_data_cap->h_adjusted, /* adjust up */ +- MXC_JPEG_MAX_HEIGHT, +- q_data_cap->fmt->v_align, +- 0); +- dev_dbg(dev, "Detected jpeg res=(%dx%d)->(%dx%d), pixfmt=%c%c%c%c\n", +- q_data_cap->w, q_data_cap->h, +- q_data_cap->w_adjusted, q_data_cap->h_adjusted, +- (fourcc & 0xff), +- (fourcc >> 8) & 0xff, +- (fourcc >> 16) & 0xff, +- (fourcc >> 24) & 0xff); +- +- /* setup bytesperline/sizeimage for capture queue */ +- mxc_jpeg_bytesperline(q_data_cap, header.frame.precision); +- mxc_jpeg_sizeimage(q_data_cap); ++ jpeg_src_buf->fmt = mxc_jpeg_find_format(ctx, fourcc); ++ jpeg_src_buf->w = header.frame.width; ++ jpeg_src_buf->h = header.frame.height; ++ ctx->header_parsed = true; + +- /* +- * if the CAPTURE format was updated with new values, regardless of +- * whether they match the values set by the client or not, signal +- * a source change event +- */ +- if (src_chg) +- notify_src_chg(ctx); ++ if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx)) ++ mxc_jpeg_source_change(ctx, jpeg_src_buf); + + return 0; + } +@@ -1327,6 +1426,20 @@ static void mxc_jpeg_buf_queue(struct vb2_buffer *vb) + struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct mxc_jpeg_src_buf *jpeg_src_buf; + ++ if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) && ++ vb2_is_streaming(vb->vb2_queue) && ++ v4l2_m2m_dst_buf_is_last(ctx->fh.m2m_ctx)) { ++ struct mxc_jpeg_q_data *q_data; ++ ++ q_data = mxc_jpeg_get_q_data(ctx, vb->vb2_queue->type); ++ vbuf->field = V4L2_FIELD_NONE; ++ vbuf->sequence = q_data->sequence++; ++ v4l2_m2m_last_buffer_done(ctx->fh.m2m_ctx, vbuf); ++ notify_eos(ctx); ++ ctx->header_parsed = false; ++ return; ++ } ++ + if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + goto end; + +@@ -1336,10 +1449,7 @@ static void mxc_jpeg_buf_queue(struct vb2_buffer *vb) + + jpeg_src_buf = vb2_to_mxc_buf(vb); + jpeg_src_buf->jpeg_parse_error = false; +- ret = mxc_jpeg_parse(ctx, +- (u8 *)vb2_plane_vaddr(vb, 0), +- vb2_get_plane_payload(vb, 0), +- &jpeg_src_buf->dht_needed); ++ ret = mxc_jpeg_parse(ctx, vb); + if (ret) + jpeg_src_buf->jpeg_parse_error = true; + +@@ -1379,6 +1489,10 @@ static int mxc_jpeg_buf_prepare(struct vb2_buffer *vb) + } + vb2_set_plane_payload(vb, i, sizeimage); + } ++ if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type)) { ++ vb2_set_plane_payload(vb, 0, 0); ++ vb2_set_plane_payload(vb, 1, 0); ++ } + return 0; + } + +@@ -1448,7 +1562,7 @@ static void mxc_jpeg_set_default_params(struct mxc_jpeg_ctx *ctx) + q[i]->h = MXC_JPEG_DEFAULT_HEIGHT; + q[i]->w_adjusted = MXC_JPEG_DEFAULT_WIDTH; + q[i]->h_adjusted = MXC_JPEG_DEFAULT_HEIGHT; +- mxc_jpeg_bytesperline(q[i], 8); ++ mxc_jpeg_bytesperline(q[i], q[i]->fmt->precision); + mxc_jpeg_sizeimage(q[i]); + } + } +@@ -1523,26 +1637,42 @@ static int mxc_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) + { + struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv); ++ struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, f->type); + +- if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE) ++ if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE) { + return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f, + MXC_JPEG_FMT_TYPE_ENC); +- else ++ } else if (!ctx->header_parsed) { + return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f, + MXC_JPEG_FMT_TYPE_RAW); ++ } else { ++ /* For the decoder CAPTURE queue, only enumerate the raw formats ++ * supported for the format currently active on OUTPUT ++ * (more precisely what was propagated on capture queue ++ * after jpeg parse on the output buffer) ++ */ ++ if (f->index) ++ return -EINVAL; ++ f->pixelformat = q_data->fmt->fourcc; ++ strscpy(f->description, q_data->fmt->name, sizeof(f->description)); ++ return 0; ++ } + } + + static int mxc_jpeg_enum_fmt_vid_out(struct file *file, void *priv, + struct v4l2_fmtdesc *f) + { + struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv); ++ u32 type = ctx->mxc_jpeg->mode == MXC_JPEG_DECODE ? MXC_JPEG_FMT_TYPE_ENC : ++ MXC_JPEG_FMT_TYPE_RAW; ++ int ret; + ++ ret = enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f, type); ++ if (ret) ++ return ret; + if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE) +- return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f, +- MXC_JPEG_FMT_TYPE_ENC); +- else +- return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f, +- MXC_JPEG_FMT_TYPE_RAW); ++ f->flags = V4L2_FMT_FLAG_DYN_RESOLUTION; ++ return 0; + } + + static int mxc_jpeg_try_fmt(struct v4l2_format *f, const struct mxc_jpeg_fmt *fmt, +@@ -1562,22 +1692,17 @@ static int mxc_jpeg_try_fmt(struct v4l2_format *f, const struct mxc_jpeg_fmt *fm + pix_mp->num_planes = fmt->colplanes; + pix_mp->pixelformat = fmt->fourcc; + +- /* +- * use MXC_JPEG_H_ALIGN instead of fmt->v_align, for vertical +- * alignment, to loosen up the alignment to multiple of 8, +- * otherwise NV12-1080p fails as 1080 is not a multiple of 16 +- */ ++ pix_mp->width = w; ++ pix_mp->height = h; + v4l_bound_align_image(&w, +- MXC_JPEG_MIN_WIDTH, +- w, /* adjust downwards*/ ++ w, /* adjust upwards*/ ++ MXC_JPEG_MAX_WIDTH, + fmt->h_align, + &h, +- MXC_JPEG_MIN_HEIGHT, +- h, /* adjust downwards*/ +- MXC_JPEG_H_ALIGN, ++ h, /* adjust upwards*/ ++ MXC_JPEG_MAX_HEIGHT, ++ 0, + 0); +- pix_mp->width = w; /* negotiate the width */ +- pix_mp->height = h; /* negotiate the height */ + + /* get user input into the tmp_q */ + tmp_q.w = w; +@@ -1590,7 +1715,7 @@ static int mxc_jpeg_try_fmt(struct v4l2_format *f, const struct mxc_jpeg_fmt *fm + } + + /* calculate bytesperline & sizeimage into the tmp_q */ +- mxc_jpeg_bytesperline(&tmp_q, 8); ++ mxc_jpeg_bytesperline(&tmp_q, fmt->precision); + mxc_jpeg_sizeimage(&tmp_q); + + /* adjust user format according to our calculations */ +@@ -1703,35 +1828,19 @@ static int mxc_jpeg_s_fmt(struct mxc_jpeg_ctx *ctx, + + q_data->w_adjusted = q_data->w; + q_data->h_adjusted = q_data->h; +- if (jpeg->mode == MXC_JPEG_DECODE) { +- /* +- * align up the resolution for CAST IP, +- * but leave the buffer resolution unchanged +- */ +- v4l_bound_align_image(&q_data->w_adjusted, +- q_data->w_adjusted, /* adjust upwards */ +- MXC_JPEG_MAX_WIDTH, +- q_data->fmt->h_align, +- &q_data->h_adjusted, +- q_data->h_adjusted, /* adjust upwards */ +- MXC_JPEG_MAX_HEIGHT, +- q_data->fmt->v_align, +- 0); +- } else { +- /* +- * align down the resolution for CAST IP, +- * but leave the buffer resolution unchanged +- */ +- v4l_bound_align_image(&q_data->w_adjusted, +- MXC_JPEG_MIN_WIDTH, +- q_data->w_adjusted, /* adjust downwards*/ +- q_data->fmt->h_align, +- &q_data->h_adjusted, +- MXC_JPEG_MIN_HEIGHT, +- q_data->h_adjusted, /* adjust downwards*/ +- q_data->fmt->v_align, +- 0); +- } ++ /* ++ * align up the resolution for CAST IP, ++ * but leave the buffer resolution unchanged ++ */ ++ v4l_bound_align_image(&q_data->w_adjusted, ++ q_data->w_adjusted, /* adjust upwards */ ++ MXC_JPEG_MAX_WIDTH, ++ q_data->fmt->h_align, ++ &q_data->h_adjusted, ++ q_data->h_adjusted, /* adjust upwards */ ++ MXC_JPEG_MAX_HEIGHT, ++ q_data->fmt->v_align, ++ 0); + + for (i = 0; i < pix_mp->num_planes; i++) { + q_data->bytesperline[i] = pix_mp->plane_fmt[i].bytesperline; +@@ -1813,27 +1922,6 @@ static int mxc_jpeg_subscribe_event(struct v4l2_fh *fh, + } + } + +-static int mxc_jpeg_dqbuf(struct file *file, void *priv, +- struct v4l2_buffer *buf) +-{ +- struct v4l2_fh *fh = file->private_data; +- struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv); +- struct device *dev = ctx->mxc_jpeg->dev; +- int num_src_ready = v4l2_m2m_num_src_bufs_ready(fh->m2m_ctx); +- int ret; +- +- dev_dbg(dev, "DQBUF type=%d, index=%d", buf->type, buf->index); +- if (ctx->stopping == 1 && num_src_ready == 0) { +- /* No more src bufs, notify app EOS */ +- notify_eos(ctx); +- ctx->stopping = 0; +- } +- +- ret = v4l2_m2m_dqbuf(file, fh->m2m_ctx, buf); +- +- return ret; +-} +- + static const struct v4l2_ioctl_ops mxc_jpeg_ioctl_ops = { + .vidioc_querycap = mxc_jpeg_querycap, + .vidioc_enum_fmt_vid_cap = mxc_jpeg_enum_fmt_vid_cap, +@@ -1857,7 +1945,7 @@ static const struct v4l2_ioctl_ops mxc_jpeg_ioctl_ops = { + .vidioc_encoder_cmd = mxc_jpeg_encoder_cmd, + + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, +- .vidioc_dqbuf = mxc_jpeg_dqbuf, ++ .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, + + .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, + .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, +@@ -1900,6 +1988,7 @@ static const struct v4l2_file_operations mxc_jpeg_fops = { + }; + + static const struct v4l2_m2m_ops mxc_jpeg_m2m_ops = { ++ .job_ready = mxc_jpeg_job_ready, + .device_run = mxc_jpeg_device_run, + }; + +@@ -1950,8 +2039,7 @@ static int mxc_jpeg_attach_pm_domains(struct mxc_jpeg_dev *jpeg) + + jpeg->pd_link[i] = device_link_add(dev, jpeg->pd_dev[i], + DL_FLAG_STATELESS | +- DL_FLAG_PM_RUNTIME | +- DL_FLAG_RPM_ACTIVE); ++ DL_FLAG_PM_RUNTIME); + if (!jpeg->pd_link[i]) { + ret = -EINVAL; + goto fail; +@@ -2016,6 +2104,21 @@ static int mxc_jpeg_probe(struct platform_device *pdev) + jpeg->dev = dev; + jpeg->mode = mode; + ++ /* Get clocks */ ++ jpeg->clk_ipg = devm_clk_get(dev, "ipg"); ++ if (IS_ERR(jpeg->clk_ipg)) { ++ dev_err(dev, "failed to get clock: ipg\n"); ++ ret = PTR_ERR(jpeg->clk_ipg); ++ goto err_clk; ++ } ++ ++ jpeg->clk_per = devm_clk_get(dev, "per"); ++ if (IS_ERR(jpeg->clk_per)) { ++ dev_err(dev, "failed to get clock: per\n"); ++ ret = PTR_ERR(jpeg->clk_per); ++ goto err_clk; ++ } ++ + ret = mxc_jpeg_attach_pm_domains(jpeg); + if (ret < 0) { + dev_err(dev, "failed to attach power domains %d\n", ret); +@@ -2084,6 +2187,7 @@ static int mxc_jpeg_probe(struct platform_device *pdev) + jpeg->dec_vdev->minor); + + platform_set_drvdata(pdev, jpeg); ++ pm_runtime_enable(dev); + + return 0; + +@@ -2100,9 +2204,52 @@ err_register: + mxc_jpeg_detach_pm_domains(jpeg); + + err_irq: ++err_clk: + return ret; + } + ++#ifdef CONFIG_PM ++static int mxc_jpeg_runtime_resume(struct device *dev) ++{ ++ struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = clk_prepare_enable(jpeg->clk_ipg); ++ if (ret < 0) { ++ dev_err(dev, "failed to enable clock: ipg\n"); ++ goto err_ipg; ++ } ++ ++ ret = clk_prepare_enable(jpeg->clk_per); ++ if (ret < 0) { ++ dev_err(dev, "failed to enable clock: per\n"); ++ goto err_per; ++ } ++ ++ return 0; ++ ++err_per: ++ clk_disable_unprepare(jpeg->clk_ipg); ++err_ipg: ++ return ret; ++} ++ ++static int mxc_jpeg_runtime_suspend(struct device *dev) ++{ ++ struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev); ++ ++ clk_disable_unprepare(jpeg->clk_ipg); ++ clk_disable_unprepare(jpeg->clk_per); ++ ++ return 0; ++} ++#endif ++ ++static const struct dev_pm_ops mxc_jpeg_pm_ops = { ++ SET_RUNTIME_PM_OPS(mxc_jpeg_runtime_suspend, ++ mxc_jpeg_runtime_resume, NULL) ++}; ++ + static int mxc_jpeg_remove(struct platform_device *pdev) + { + unsigned int slot; +@@ -2111,6 +2258,7 @@ static int mxc_jpeg_remove(struct platform_device *pdev) + for (slot = 0; slot < MXC_MAX_SLOTS; slot++) + mxc_jpeg_free_slot_data(jpeg, slot); + ++ pm_runtime_disable(&pdev->dev); + video_unregister_device(jpeg->dec_vdev); + v4l2_m2m_release(jpeg->m2m_dev); + v4l2_device_unregister(&jpeg->v4l2_dev); +@@ -2127,6 +2275,7 @@ static struct platform_driver mxc_jpeg_driver = { + .driver = { + .name = "mxc-jpeg", + .of_match_table = mxc_jpeg_match, ++ .pm = &mxc_jpeg_pm_ops, + }, + }; + module_platform_driver(mxc_jpeg_driver); +diff --git a/drivers/media/platform/imx-jpeg/mxc-jpeg.h b/drivers/media/platform/imx-jpeg/mxc-jpeg.h +index 4c210852e876c..542993eb8d5b0 100644 +--- a/drivers/media/platform/imx-jpeg/mxc-jpeg.h ++++ b/drivers/media/platform/imx-jpeg/mxc-jpeg.h +@@ -49,6 +49,7 @@ enum mxc_jpeg_mode { + * @h_align: horizontal alignment order (align to 2^h_align) + * @v_align: vertical alignment order (align to 2^v_align) + * @flags: flags describing format applicability ++ * @precision: jpeg sample precision + */ + struct mxc_jpeg_fmt { + const char *name; +@@ -60,6 +61,7 @@ struct mxc_jpeg_fmt { + int h_align; + int v_align; + u32 flags; ++ u8 precision; + }; + + struct mxc_jpeg_desc { +@@ -90,8 +92,9 @@ struct mxc_jpeg_ctx { + struct mxc_jpeg_q_data cap_q; + struct v4l2_fh fh; + enum mxc_jpeg_enc_state enc_state; +- unsigned int stopping; + unsigned int slot; ++ unsigned int source_change; ++ bool header_parsed; + }; + + struct mxc_jpeg_slot_data { +@@ -109,6 +112,8 @@ struct mxc_jpeg_dev { + spinlock_t hw_lock; /* hardware access lock */ + unsigned int mode; + struct mutex lock; /* v4l2 ioctls serialization */ ++ struct clk *clk_ipg; ++ struct clk *clk_per; + struct platform_device *pdev; + struct device *dev; + void __iomem *base_reg; +diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h b/drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h +index 2cb8cecb30771..b810c96695c83 100644 +--- a/drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h ++++ b/drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h +@@ -40,12 +40,14 @@ struct mdp_ipi_init { + * @ipi_id : IPI_MDP + * @ap_inst : AP mtk_mdp_vpu address + * @vpu_inst_addr : VPU MDP instance address ++ * @padding : Alignment padding + */ + struct mdp_ipi_comm { + uint32_t msg_id; + uint32_t ipi_id; + uint64_t ap_inst; + uint32_t vpu_inst_addr; ++ uint32_t padding; + }; + + /** +diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c +index 60e57e0f19272..fd7d2a9d0449a 100644 +--- a/drivers/media/usb/hdpvr/hdpvr-video.c ++++ b/drivers/media/usb/hdpvr/hdpvr-video.c +@@ -409,7 +409,7 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, + struct hdpvr_device *dev = video_drvdata(file); + struct hdpvr_buffer *buf = NULL; + struct urb *urb; +- unsigned int ret = 0; ++ int ret = 0; + int rem, cnt; + + if (*pos) +diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c +index 3de683b5e06d0..8aeed39c415f2 100644 +--- a/drivers/media/v4l2-core/v4l2-mem2mem.c ++++ b/drivers/media/v4l2-core/v4l2-mem2mem.c +@@ -924,7 +924,7 @@ static __poll_t v4l2_m2m_poll_for_data(struct file *file, + if ((!src_q->streaming || src_q->error || + list_empty(&src_q->queued_list)) && + (!dst_q->streaming || dst_q->error || +- list_empty(&dst_q->queued_list))) ++ (list_empty(&dst_q->queued_list) && !dst_q->last_buffer_dequeued))) + return EPOLLERR; + + spin_lock_irqsave(&src_q->done_lock, flags); +diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c +index 487e4cc2951e0..f854822f84d6c 100644 +--- a/drivers/memstick/core/ms_block.c ++++ b/drivers/memstick/core/ms_block.c +@@ -1341,17 +1341,17 @@ static int msb_ftl_initialize(struct msb_data *msb) + msb->zone_count = msb->block_count / MS_BLOCKS_IN_ZONE; + msb->logical_block_count = msb->zone_count * 496 - 2; + +- msb->used_blocks_bitmap = kzalloc(msb->block_count / 8, GFP_KERNEL); +- msb->erased_blocks_bitmap = kzalloc(msb->block_count / 8, GFP_KERNEL); ++ msb->used_blocks_bitmap = bitmap_zalloc(msb->block_count, GFP_KERNEL); ++ msb->erased_blocks_bitmap = bitmap_zalloc(msb->block_count, GFP_KERNEL); + msb->lba_to_pba_table = + kmalloc_array(msb->logical_block_count, sizeof(u16), + GFP_KERNEL); + + if (!msb->used_blocks_bitmap || !msb->lba_to_pba_table || + !msb->erased_blocks_bitmap) { +- kfree(msb->used_blocks_bitmap); ++ bitmap_free(msb->used_blocks_bitmap); ++ bitmap_free(msb->erased_blocks_bitmap); + kfree(msb->lba_to_pba_table); +- kfree(msb->erased_blocks_bitmap); + return -ENOMEM; + } + +@@ -1962,7 +1962,8 @@ static int msb_bd_open(struct block_device *bdev, fmode_t mode) + static void msb_data_clear(struct msb_data *msb) + { + kfree(msb->boot_page); +- kfree(msb->used_blocks_bitmap); ++ bitmap_free(msb->used_blocks_bitmap); ++ bitmap_free(msb->erased_blocks_bitmap); + kfree(msb->lba_to_pba_table); + kfree(msb->cache); + msb->card = NULL; +diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c +index fec2096474ad1..a6661e07035ba 100644 +--- a/drivers/mfd/max77620.c ++++ b/drivers/mfd/max77620.c +@@ -419,9 +419,11 @@ static int max77620_initialise_fps(struct max77620_chip *chip) + ret = max77620_config_fps(chip, fps_child); + if (ret < 0) { + of_node_put(fps_child); ++ of_node_put(fps_np); + return ret; + } + } ++ of_node_put(fps_np); + + config = chip->enable_global_lpm ? MAX77620_ONOFFCNFG2_SLP_LPM_MSK : 0; + ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2, +diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c +index 5369c67e3280d..663ffd4b85706 100644 +--- a/drivers/mfd/t7l66xb.c ++++ b/drivers/mfd/t7l66xb.c +@@ -397,11 +397,8 @@ err_noirq: + + static int t7l66xb_remove(struct platform_device *dev) + { +- struct t7l66xb_platform_data *pdata = dev_get_platdata(&dev->dev); + struct t7l66xb *t7l66xb = platform_get_drvdata(dev); +- int ret; + +- ret = pdata->disable(dev); + clk_disable_unprepare(t7l66xb->clk48m); + clk_put(t7l66xb->clk48m); + clk_disable_unprepare(t7l66xb->clk32k); +@@ -412,8 +409,7 @@ static int t7l66xb_remove(struct platform_device *dev) + mfd_remove_devices(&dev->dev); + kfree(t7l66xb); + +- return ret; +- ++ return 0; + } + + static struct platform_driver t7l66xb_platform_driver = { +diff --git a/drivers/misc/cardreader/rtsx_pcr.c b/drivers/misc/cardreader/rtsx_pcr.c +index 5121edb0d9eff..62fdbbd55e740 100644 +--- a/drivers/misc/cardreader/rtsx_pcr.c ++++ b/drivers/misc/cardreader/rtsx_pcr.c +@@ -1581,7 +1581,7 @@ static int rtsx_pci_probe(struct pci_dev *pcidev, + pcr->remap_addr = ioremap(base, len); + if (!pcr->remap_addr) { + ret = -ENOMEM; +- goto free_handle; ++ goto free_idr; + } + + pcr->rtsx_resv_buf = dma_alloc_coherent(&(pcidev->dev), +@@ -1651,6 +1651,10 @@ disable_msi: + pcr->rtsx_resv_buf, pcr->rtsx_resv_buf_addr); + unmap: + iounmap(pcr->remap_addr); ++free_idr: ++ spin_lock(&rtsx_pci_lock); ++ idr_remove(&rtsx_pci_idr, pcr->id); ++ spin_unlock(&rtsx_pci_lock); + free_handle: + kfree(handle); + free_pcr: +diff --git a/drivers/misc/eeprom/idt_89hpesx.c b/drivers/misc/eeprom/idt_89hpesx.c +index b0cff4b152da8..7f430742ce2b8 100644 +--- a/drivers/misc/eeprom/idt_89hpesx.c ++++ b/drivers/misc/eeprom/idt_89hpesx.c +@@ -909,14 +909,18 @@ static ssize_t idt_dbgfs_csr_write(struct file *filep, const char __user *ubuf, + u32 csraddr, csrval; + char *buf; + ++ if (*offp) ++ return 0; ++ + /* Copy data from User-space */ + buf = kmalloc(count + 1, GFP_KERNEL); + if (!buf) + return -ENOMEM; + +- ret = simple_write_to_buffer(buf, count, offp, ubuf, count); +- if (ret < 0) ++ if (copy_from_user(buf, ubuf, count)) { ++ ret = -EFAULT; + goto free_buf; ++ } + buf[count] = 0; + + /* Find position of colon in the buffer */ +diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c +index a196116444a38..3222a9d0c2451 100644 +--- a/drivers/mmc/core/block.c ++++ b/drivers/mmc/core/block.c +@@ -175,7 +175,7 @@ static inline int mmc_blk_part_switch(struct mmc_card *card, + unsigned int part_type); + static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, + struct mmc_card *card, +- int disable_multi, ++ int recovery_mode, + struct mmc_queue *mq); + static void mmc_blk_hsq_req_done(struct mmc_request *mrq); + +@@ -1285,7 +1285,7 @@ static void mmc_blk_eval_resp_error(struct mmc_blk_request *brq) + } + + static void mmc_blk_data_prep(struct mmc_queue *mq, struct mmc_queue_req *mqrq, +- int disable_multi, bool *do_rel_wr_p, ++ int recovery_mode, bool *do_rel_wr_p, + bool *do_data_tag_p) + { + struct mmc_blk_data *md = mq->blkdata; +@@ -1351,12 +1351,12 @@ static void mmc_blk_data_prep(struct mmc_queue *mq, struct mmc_queue_req *mqrq, + brq->data.blocks--; + + /* +- * After a read error, we redo the request one sector ++ * After a read error, we redo the request one (native) sector + * at a time in order to accurately determine which + * sectors can be read successfully. + */ +- if (disable_multi) +- brq->data.blocks = 1; ++ if (recovery_mode) ++ brq->data.blocks = queue_physical_block_size(mq->queue) >> 9; + + /* + * Some controllers have HW issues while operating +@@ -1573,7 +1573,7 @@ static int mmc_blk_cqe_issue_rw_rq(struct mmc_queue *mq, struct request *req) + + static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, + struct mmc_card *card, +- int disable_multi, ++ int recovery_mode, + struct mmc_queue *mq) + { + u32 readcmd, writecmd; +@@ -1582,7 +1582,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, + struct mmc_blk_data *md = mq->blkdata; + bool do_rel_wr, do_data_tag; + +- mmc_blk_data_prep(mq, mqrq, disable_multi, &do_rel_wr, &do_data_tag); ++ mmc_blk_data_prep(mq, mqrq, recovery_mode, &do_rel_wr, &do_data_tag); + + brq->mrq.cmd = &brq->cmd; + +@@ -1673,7 +1673,7 @@ static int mmc_blk_fix_state(struct mmc_card *card, struct request *req) + + #define MMC_READ_SINGLE_RETRIES 2 + +-/* Single sector read during recovery */ ++/* Single (native) sector read during recovery */ + static void mmc_blk_read_single(struct mmc_queue *mq, struct request *req) + { + struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req); +@@ -1681,6 +1681,7 @@ static void mmc_blk_read_single(struct mmc_queue *mq, struct request *req) + struct mmc_card *card = mq->card; + struct mmc_host *host = card->host; + blk_status_t error = BLK_STS_OK; ++ size_t bytes_per_read = queue_physical_block_size(mq->queue); + + do { + u32 status; +@@ -1715,13 +1716,13 @@ static void mmc_blk_read_single(struct mmc_queue *mq, struct request *req) + else + error = BLK_STS_OK; + +- } while (blk_update_request(req, error, 512)); ++ } while (blk_update_request(req, error, bytes_per_read)); + + return; + + error_exit: + mrq->data->bytes_xfered = 0; +- blk_update_request(req, BLK_STS_IOERR, 512); ++ blk_update_request(req, BLK_STS_IOERR, bytes_per_read); + /* Let it try the remaining request again */ + if (mqrq->retries > MMC_MAX_RETRIES - 1) + mqrq->retries = MMC_MAX_RETRIES - 1; +@@ -1862,10 +1863,9 @@ static void mmc_blk_mq_rw_recovery(struct mmc_queue *mq, struct request *req) + return; + } + +- /* FIXME: Missing single sector read for large sector size */ +- if (!mmc_large_sector(card) && rq_data_dir(req) == READ && +- brq->data.blocks > 1) { +- /* Read one sector at a time */ ++ if (rq_data_dir(req) == READ && brq->data.blocks > ++ queue_physical_block_size(mq->queue) >> 9) { ++ /* Read one (native) sector at a time */ + mmc_blk_read_single(mq, req); + return; + } +diff --git a/drivers/mmc/host/cavium-octeon.c b/drivers/mmc/host/cavium-octeon.c +index 2c4b2df52adb1..12dca91a8ef61 100644 +--- a/drivers/mmc/host/cavium-octeon.c ++++ b/drivers/mmc/host/cavium-octeon.c +@@ -277,6 +277,7 @@ static int octeon_mmc_probe(struct platform_device *pdev) + if (ret) { + dev_err(&pdev->dev, "Error populating slots\n"); + octeon_mmc_set_shared_power(host, 0); ++ of_node_put(cn); + goto error; + } + i++; +diff --git a/drivers/mmc/host/cavium-thunderx.c b/drivers/mmc/host/cavium-thunderx.c +index 76013bbbcff30..202b1d6da678c 100644 +--- a/drivers/mmc/host/cavium-thunderx.c ++++ b/drivers/mmc/host/cavium-thunderx.c +@@ -142,8 +142,10 @@ static int thunder_mmc_probe(struct pci_dev *pdev, + continue; + + ret = cvm_mmc_of_slot_probe(&host->slot_pdev[i]->dev, host); +- if (ret) ++ if (ret) { ++ of_node_put(child_node); + goto error; ++ } + } + i++; + } +diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c +index 2fe6fcdbb1b30..9bf95ba217fac 100644 +--- a/drivers/mmc/host/mxcmmc.c ++++ b/drivers/mmc/host/mxcmmc.c +@@ -1025,7 +1025,7 @@ static int mxcmci_probe(struct platform_device *pdev) + mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; + mmc->max_seg_size = mmc->max_req_size; + +- host->devtype = (enum mxcmci_type)of_device_get_match_data(&pdev->dev); ++ host->devtype = (uintptr_t)of_device_get_match_data(&pdev->dev); + + /* adjust max_segs after devtype detection */ + if (!is_mpc512x_mmc(host)) +diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c +index ae689bf54686f..791e180a06170 100644 +--- a/drivers/mmc/host/renesas_sdhi_core.c ++++ b/drivers/mmc/host/renesas_sdhi_core.c +@@ -925,6 +925,10 @@ int renesas_sdhi_probe(struct platform_device *pdev, + if (IS_ERR(priv->clk_cd)) + priv->clk_cd = NULL; + ++ priv->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); ++ if (IS_ERR(priv->rstc)) ++ return PTR_ERR(priv->rstc); ++ + priv->pinctrl = devm_pinctrl_get(&pdev->dev); + if (!IS_ERR(priv->pinctrl)) { + priv->pins_default = pinctrl_lookup_state(priv->pinctrl, +@@ -1013,10 +1017,6 @@ int renesas_sdhi_probe(struct platform_device *pdev, + if (ret) + goto efree; + +- priv->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); +- if (IS_ERR(priv->rstc)) +- return PTR_ERR(priv->rstc); +- + ver = sd_ctrl_read16(host, CTL_VERSION); + /* GEN2_SDR104 is first known SDHI to use 32bit block count */ + if (ver < SDHI_VER_GEN2_SDR104 && mmc_data->max_blk_count > U16_MAX) +diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c +index d1a1c548c515f..0452c312b65eb 100644 +--- a/drivers/mmc/host/sdhci-of-at91.c ++++ b/drivers/mmc/host/sdhci-of-at91.c +@@ -100,8 +100,13 @@ static void sdhci_at91_set_clock(struct sdhci_host *host, unsigned int clock) + static void sdhci_at91_set_uhs_signaling(struct sdhci_host *host, + unsigned int timing) + { +- if (timing == MMC_TIMING_MMC_DDR52) +- sdhci_writeb(host, SDMMC_MC1R_DDR, SDMMC_MC1R); ++ u8 mc1r; ++ ++ if (timing == MMC_TIMING_MMC_DDR52) { ++ mc1r = sdhci_readb(host, SDMMC_MC1R); ++ mc1r |= SDMMC_MC1R_DDR; ++ sdhci_writeb(host, mc1r, SDMMC_MC1R); ++ } + sdhci_set_uhs_signaling(host, timing); + } + +diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c +index 0f3658b36513c..04a37fd137ee1 100644 +--- a/drivers/mmc/host/sdhci-of-esdhc.c ++++ b/drivers/mmc/host/sdhci-of-esdhc.c +@@ -904,6 +904,7 @@ static int esdhc_signal_voltage_switch(struct mmc_host *mmc, + scfg_node = of_find_matching_node(NULL, scfg_device_ids); + if (scfg_node) + scfg_base = of_iomap(scfg_node, 0); ++ of_node_put(scfg_node); + if (scfg_base) { + sdhciovselcr = SDHCIOVSELCR_TGLEN | + SDHCIOVSELCR_VSELVAL; +diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c +index 2b317ed6c103f..9c714c982c6ec 100644 +--- a/drivers/mtd/devices/mtd_dataflash.c ++++ b/drivers/mtd/devices/mtd_dataflash.c +@@ -112,6 +112,13 @@ static const struct of_device_id dataflash_dt_ids[] = { + MODULE_DEVICE_TABLE(of, dataflash_dt_ids); + #endif + ++static const struct spi_device_id dataflash_spi_ids[] = { ++ { .name = "at45", }, ++ { .name = "dataflash", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(spi, dataflash_spi_ids); ++ + /* ......................................................................... */ + + /* +@@ -938,6 +945,7 @@ static struct spi_driver dataflash_driver = { + + .probe = dataflash_probe, + .remove = dataflash_remove, ++ .id_table = dataflash_spi_ids, + + /* FIXME: investigate suspend and resume... */ + }; +diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c +index 983999c020d66..48bda2dd1bb55 100644 +--- a/drivers/mtd/devices/st_spi_fsm.c ++++ b/drivers/mtd/devices/st_spi_fsm.c +@@ -2115,10 +2115,12 @@ static int stfsm_probe(struct platform_device *pdev) + (long long)fsm->mtd.size, (long long)(fsm->mtd.size >> 20), + fsm->mtd.erasesize, (fsm->mtd.erasesize >> 10)); + +- return mtd_device_register(&fsm->mtd, NULL, 0); +- ++ ret = mtd_device_register(&fsm->mtd, NULL, 0); ++ if (ret) { + err_clk_unprepare: +- clk_disable_unprepare(fsm->clk); ++ clk_disable_unprepare(fsm->clk); ++ } ++ + return ret; + } + +diff --git a/drivers/mtd/maps/physmap-versatile.c b/drivers/mtd/maps/physmap-versatile.c +index ad7cd9cfaee04..a1b8b7b25f88b 100644 +--- a/drivers/mtd/maps/physmap-versatile.c ++++ b/drivers/mtd/maps/physmap-versatile.c +@@ -93,6 +93,7 @@ static int ap_flash_init(struct platform_device *pdev) + return -ENODEV; + } + ebi_base = of_iomap(ebi, 0); ++ of_node_put(ebi); + if (!ebi_base) + return -ENODEV; + +@@ -207,6 +208,7 @@ int of_flash_probe_versatile(struct platform_device *pdev, + + versatile_flashprot = (enum versatile_flashprot)devid->data; + rmap = syscon_node_to_regmap(sysnp); ++ of_node_put(sysnp); + if (IS_ERR(rmap)) + return PTR_ERR(rmap); + +diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c +index 53bd10738418b..296fb16c8dc3c 100644 +--- a/drivers/mtd/nand/raw/arasan-nand-controller.c ++++ b/drivers/mtd/nand/raw/arasan-nand-controller.c +@@ -347,17 +347,17 @@ static int anfc_select_target(struct nand_chip *chip, int target) + + /* Update clock frequency */ + if (nfc->cur_clk != anand->clk) { +- clk_disable_unprepare(nfc->controller_clk); +- ret = clk_set_rate(nfc->controller_clk, anand->clk); ++ clk_disable_unprepare(nfc->bus_clk); ++ ret = clk_set_rate(nfc->bus_clk, anand->clk); + if (ret) { + dev_err(nfc->dev, "Failed to change clock rate\n"); + return ret; + } + +- ret = clk_prepare_enable(nfc->controller_clk); ++ ret = clk_prepare_enable(nfc->bus_clk); + if (ret) { + dev_err(nfc->dev, +- "Failed to re-enable the controller clock\n"); ++ "Failed to re-enable the bus clock\n"); + return ret; + } + +@@ -1043,7 +1043,13 @@ static int anfc_setup_interface(struct nand_chip *chip, int target, + DQS_BUFF_SEL_OUT(dqs_mode); + } + +- anand->clk = ANFC_XLNX_SDR_DFLT_CORE_CLK; ++ if (nand_interface_is_sdr(conf)) { ++ anand->clk = ANFC_XLNX_SDR_DFLT_CORE_CLK; ++ } else { ++ /* ONFI timings are defined in picoseconds */ ++ anand->clk = div_u64((u64)NSEC_PER_SEC * 1000, ++ conf->timings.nvddr.tCK_min); ++ } + + /* + * Due to a hardware bug in the ZynqMP SoC, SDR timing modes 0-1 work +diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c +index ac3be92872d06..0321801833393 100644 +--- a/drivers/mtd/nand/raw/meson_nand.c ++++ b/drivers/mtd/nand/raw/meson_nand.c +@@ -1307,7 +1307,6 @@ static int meson_nfc_nand_chip_cleanup(struct meson_nfc *nfc) + if (ret) + return ret; + +- meson_nfc_free_buffer(&meson_chip->nand); + nand_cleanup(&meson_chip->nand); + list_del(&meson_chip->node); + } +diff --git a/drivers/mtd/parsers/ofpart_bcm4908.c b/drivers/mtd/parsers/ofpart_bcm4908.c +index 0eddef4c198ec..bb072a0940e48 100644 +--- a/drivers/mtd/parsers/ofpart_bcm4908.c ++++ b/drivers/mtd/parsers/ofpart_bcm4908.c +@@ -35,12 +35,15 @@ static long long bcm4908_partitions_fw_offset(void) + err = kstrtoul(s + len + 1, 0, &offset); + if (err) { + pr_err("failed to parse %s\n", s + len + 1); ++ of_node_put(root); + return err; + } + ++ of_node_put(root); + return offset << 10; + } + ++ of_node_put(root); + return -ENOENT; + } + +diff --git a/drivers/mtd/parsers/redboot.c b/drivers/mtd/parsers/redboot.c +index feb44a573d447..a16b42a885816 100644 +--- a/drivers/mtd/parsers/redboot.c ++++ b/drivers/mtd/parsers/redboot.c +@@ -58,6 +58,7 @@ static void parse_redboot_of(struct mtd_info *master) + return; + + ret = of_property_read_u32(npart, "fis-index-block", &dirblock); ++ of_node_put(npart); + if (ret) + return; + +diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c +index 0cff2cda1b5a0..7f955fade8383 100644 +--- a/drivers/mtd/sm_ftl.c ++++ b/drivers/mtd/sm_ftl.c +@@ -1111,9 +1111,9 @@ static void sm_release(struct mtd_blktrans_dev *dev) + { + struct sm_ftl *ftl = dev->priv; + +- mutex_lock(&ftl->mutex); + del_timer_sync(&ftl->timer); + cancel_work_sync(&ftl->flush_work); ++ mutex_lock(&ftl->mutex); + sm_cache_flush(ftl); + mutex_unlock(&ftl->mutex); + } +diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c +index d97cdbc2b9de3..eb5d7b3d18609 100644 +--- a/drivers/mtd/spi-nor/core.c ++++ b/drivers/mtd/spi-nor/core.c +@@ -177,7 +177,7 @@ static int spi_nor_controller_ops_write_reg(struct spi_nor *nor, u8 opcode, + + static int spi_nor_controller_ops_erase(struct spi_nor *nor, loff_t offs) + { +- if (spi_nor_protocol_is_dtr(nor->write_proto)) ++ if (spi_nor_protocol_is_dtr(nor->reg_proto)) + return -EOPNOTSUPP; + + return nor->controller_ops->erase(nor, offs); +@@ -1195,7 +1195,7 @@ static int spi_nor_erase_chip(struct spi_nor *nor) + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_NO_DATA); + +- spi_nor_spimem_setup_op(nor, &op, nor->write_proto); ++ spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + + ret = spi_mem_exec_op(nor->spimem, &op); + } else { +@@ -1340,7 +1340,7 @@ int spi_nor_erase_sector(struct spi_nor *nor, u32 addr) + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_NO_DATA); + +- spi_nor_spimem_setup_op(nor, &op, nor->write_proto); ++ spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + + return spi_mem_exec_op(nor->spimem, &op); + } else if (nor->controller_ops->erase) { +diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c +index 80425636049d2..29e2beae3357b 100644 +--- a/drivers/net/can/dev/netlink.c ++++ b/drivers/net/can/dev/netlink.c +@@ -76,7 +76,8 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[], + * directly via do_set_bitrate(). Bail out if neither + * is given. + */ +- if (!priv->bittiming_const && !priv->do_set_bittiming) ++ if (!priv->bittiming_const && !priv->do_set_bittiming && ++ !priv->bitrate_const) + return -EOPNOTSUPP; + + memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt)); +@@ -169,7 +170,8 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[], + * directly via do_set_bitrate(). Bail out if neither + * is given. + */ +- if (!priv->data_bittiming_const && !priv->do_set_data_bittiming) ++ if (!priv->data_bittiming_const && !priv->do_set_data_bittiming && ++ !priv->data_bitrate_const) + return -EOPNOTSUPP; + + memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]), +diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c +index 964c8a09226a9..cd8d536c6fb20 100644 +--- a/drivers/net/can/pch_can.c ++++ b/drivers/net/can/pch_can.c +@@ -489,6 +489,7 @@ static void pch_can_error(struct net_device *ndev, u32 status) + if (!skb) + return; + ++ errc = ioread32(&priv->regs->errc); + if (status & PCH_BUS_OFF) { + pch_can_set_tx_all(priv, 0); + pch_can_set_rx_all(priv, 0); +@@ -496,9 +497,11 @@ static void pch_can_error(struct net_device *ndev, u32 status) + cf->can_id |= CAN_ERR_BUSOFF; + priv->can.can_stats.bus_off++; + can_bus_off(ndev); ++ } else { ++ cf->data[6] = errc & PCH_TEC; ++ cf->data[7] = (errc & PCH_REC) >> 8; + } + +- errc = ioread32(&priv->regs->errc); + /* Warning interrupt. */ + if (status & PCH_EWARN) { + state = CAN_STATE_ERROR_WARNING; +@@ -556,9 +559,6 @@ static void pch_can_error(struct net_device *ndev, u32 status) + break; + } + +- cf->data[6] = errc & PCH_TEC; +- cf->data[7] = (errc & PCH_REC) >> 8; +- + priv->can.state = state; + netif_receive_skb(skb); + +diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c +index 8999ec9455ec2..945b319de841c 100644 +--- a/drivers/net/can/rcar/rcar_can.c ++++ b/drivers/net/can/rcar/rcar_can.c +@@ -235,11 +235,8 @@ static void rcar_can_error(struct net_device *ndev) + if (eifr & (RCAR_CAN_EIFR_EWIF | RCAR_CAN_EIFR_EPIF)) { + txerr = readb(&priv->regs->tecr); + rxerr = readb(&priv->regs->recr); +- if (skb) { ++ if (skb) + cf->can_id |= CAN_ERR_CRTL; +- cf->data[6] = txerr; +- cf->data[7] = rxerr; +- } + } + if (eifr & RCAR_CAN_EIFR_BEIF) { + int rx_errors = 0, tx_errors = 0; +@@ -339,6 +336,9 @@ static void rcar_can_error(struct net_device *ndev) + can_bus_off(ndev); + if (skb) + cf->can_id |= CAN_ERR_BUSOFF; ++ } else if (skb) { ++ cf->data[6] = txerr; ++ cf->data[7] = rxerr; + } + if (eifr & RCAR_CAN_EIFR_ORIF) { + netdev_dbg(priv->ndev, "Receive overrun error interrupt\n"); +diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c +index 3fad546467461..aae2677e24f99 100644 +--- a/drivers/net/can/sja1000/sja1000.c ++++ b/drivers/net/can/sja1000/sja1000.c +@@ -404,9 +404,6 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) + txerr = priv->read_reg(priv, SJA1000_TXERR); + rxerr = priv->read_reg(priv, SJA1000_RXERR); + +- cf->data[6] = txerr; +- cf->data[7] = rxerr; +- + if (isrc & IRQ_DOI) { + /* data overrun interrupt */ + netdev_dbg(dev, "data overrun interrupt\n"); +@@ -428,6 +425,10 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) + else + state = CAN_STATE_ERROR_ACTIVE; + } ++ if (state != CAN_STATE_BUS_OFF) { ++ cf->data[6] = txerr; ++ cf->data[7] = rxerr; ++ } + if (isrc & IRQ_BEI) { + /* bus error interrupt */ + priv->can.can_stats.bus_error++; +diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c +index 89d9c986a2297..b08b98e6ad1c9 100644 +--- a/drivers/net/can/spi/hi311x.c ++++ b/drivers/net/can/spi/hi311x.c +@@ -670,8 +670,6 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id) + + txerr = hi3110_read(spi, HI3110_READ_TEC); + rxerr = hi3110_read(spi, HI3110_READ_REC); +- cf->data[6] = txerr; +- cf->data[7] = rxerr; + tx_state = txerr >= rxerr ? new_state : 0; + rx_state = txerr <= rxerr ? new_state : 0; + can_change_state(net, cf, tx_state, rx_state); +@@ -684,6 +682,9 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id) + hi3110_hw_sleep(spi); + break; + } ++ } else { ++ cf->data[6] = txerr; ++ cf->data[7] = rxerr; + } + } + +diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c +index 54aa7c25c4de1..ad8f50807aca5 100644 +--- a/drivers/net/can/sun4i_can.c ++++ b/drivers/net/can/sun4i_can.c +@@ -525,11 +525,6 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status) + rxerr = (errc >> 16) & 0xFF; + txerr = errc & 0xFF; + +- if (skb) { +- cf->data[6] = txerr; +- cf->data[7] = rxerr; +- } +- + if (isrc & SUN4I_INT_DATA_OR) { + /* data overrun interrupt */ + netdev_dbg(dev, "data overrun interrupt\n"); +@@ -560,6 +555,10 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status) + else + state = CAN_STATE_ERROR_ACTIVE; + } ++ if (skb && state != CAN_STATE_BUS_OFF) { ++ cf->data[6] = txerr; ++ cf->data[7] = rxerr; ++ } + if (isrc & SUN4I_INT_BUS_ERR) { + /* bus error interrupt */ + netdev_dbg(dev, "bus error interrupt\n"); +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 fce3f069cdbc0..93d7ee6d17b6e 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +@@ -916,8 +916,10 @@ static void kvaser_usb_hydra_update_state(struct kvaser_usb_net_priv *priv, + new_state < CAN_STATE_BUS_OFF) + priv->can.can_stats.restarts++; + +- cf->data[6] = bec->txerr; +- cf->data[7] = bec->rxerr; ++ if (new_state != CAN_STATE_BUS_OFF) { ++ cf->data[6] = bec->txerr; ++ cf->data[7] = bec->rxerr; ++ } + + stats = &netdev->stats; + stats->rx_packets++; +@@ -1071,8 +1073,10 @@ kvaser_usb_hydra_error_frame(struct kvaser_usb_net_priv *priv, + shhwtstamps->hwtstamp = hwtstamp; + + cf->can_id |= CAN_ERR_BUSERROR; +- cf->data[6] = bec.txerr; +- cf->data[7] = bec.rxerr; ++ if (new_state != CAN_STATE_BUS_OFF) { ++ cf->data[6] = bec.txerr; ++ cf->data[7] = bec.rxerr; ++ } + + stats->rx_packets++; + stats->rx_bytes += cf->len; +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 b9c2231e4b43e..05d54c4f929fe 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -857,8 +857,10 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev, + break; + } + +- cf->data[6] = es->txerr; +- cf->data[7] = es->rxerr; ++ if (new_state != CAN_STATE_BUS_OFF) { ++ cf->data[6] = es->txerr; ++ cf->data[7] = es->rxerr; ++ } + + stats->rx_packets++; + stats->rx_bytes += cf->len; +diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c +index d4c8f934a1ce0..a5dee2ee24656 100644 +--- a/drivers/net/can/usb/usb_8dev.c ++++ b/drivers/net/can/usb/usb_8dev.c +@@ -442,9 +442,10 @@ static void usb_8dev_rx_err_msg(struct usb_8dev_priv *priv, + + if (rx_errors) + stats->rx_errors++; +- +- cf->data[6] = txerr; +- cf->data[7] = rxerr; ++ if (priv->can.state != CAN_STATE_BUS_OFF) { ++ cf->data[6] = txerr; ++ cf->data[7] = rxerr; ++ } + + priv->bec.txerr = txerr; + priv->bec.rxerr = rxerr; +diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h +index fb3e89141a0d9..a4fbf44f944cd 100644 +--- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h ++++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h +@@ -95,9 +95,6 @@ struct hinic_dev { + u16 sq_depth; + u16 rq_depth; + +- struct hinic_txq_stats tx_stats; +- struct hinic_rxq_stats rx_stats; +- + u8 rss_tmpl_idx; + u8 rss_hash_engine; + u16 num_rss; +diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c +index f8aa80ec201bd..8c6ec7c258099 100644 +--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c ++++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c +@@ -62,8 +62,6 @@ MODULE_PARM_DESC(rx_weight, "Number Rx packets for NAPI budget (default=64)"); + + #define HINIC_LRO_RX_TIMER_DEFAULT 16 + +-#define VLAN_BITMAP_SIZE(nic_dev) (ALIGN(VLAN_N_VID, 8) / 8) +- + #define work_to_rx_mode_work(work) \ + container_of(work, struct hinic_rx_mode_work, work) + +@@ -82,56 +80,44 @@ static int set_features(struct hinic_dev *nic_dev, + netdev_features_t pre_features, + netdev_features_t features, bool force_change); + +-static void update_rx_stats(struct hinic_dev *nic_dev, struct hinic_rxq *rxq) ++static void gather_rx_stats(struct hinic_rxq_stats *nic_rx_stats, struct hinic_rxq *rxq) + { +- struct hinic_rxq_stats *nic_rx_stats = &nic_dev->rx_stats; + struct hinic_rxq_stats rx_stats; + +- u64_stats_init(&rx_stats.syncp); +- + hinic_rxq_get_stats(rxq, &rx_stats); + +- u64_stats_update_begin(&nic_rx_stats->syncp); + nic_rx_stats->bytes += rx_stats.bytes; + nic_rx_stats->pkts += rx_stats.pkts; + nic_rx_stats->errors += rx_stats.errors; + nic_rx_stats->csum_errors += rx_stats.csum_errors; + nic_rx_stats->other_errors += rx_stats.other_errors; +- u64_stats_update_end(&nic_rx_stats->syncp); +- +- hinic_rxq_clean_stats(rxq); + } + +-static void update_tx_stats(struct hinic_dev *nic_dev, struct hinic_txq *txq) ++static void gather_tx_stats(struct hinic_txq_stats *nic_tx_stats, struct hinic_txq *txq) + { +- struct hinic_txq_stats *nic_tx_stats = &nic_dev->tx_stats; + struct hinic_txq_stats tx_stats; + +- u64_stats_init(&tx_stats.syncp); +- + hinic_txq_get_stats(txq, &tx_stats); + +- u64_stats_update_begin(&nic_tx_stats->syncp); + nic_tx_stats->bytes += tx_stats.bytes; + nic_tx_stats->pkts += tx_stats.pkts; + nic_tx_stats->tx_busy += tx_stats.tx_busy; + nic_tx_stats->tx_wake += tx_stats.tx_wake; + nic_tx_stats->tx_dropped += tx_stats.tx_dropped; + nic_tx_stats->big_frags_pkts += tx_stats.big_frags_pkts; +- u64_stats_update_end(&nic_tx_stats->syncp); +- +- hinic_txq_clean_stats(txq); + } + +-static void update_nic_stats(struct hinic_dev *nic_dev) ++static void gather_nic_stats(struct hinic_dev *nic_dev, ++ struct hinic_rxq_stats *nic_rx_stats, ++ struct hinic_txq_stats *nic_tx_stats) + { + int i, num_qps = hinic_hwdev_num_qps(nic_dev->hwdev); + + for (i = 0; i < num_qps; i++) +- update_rx_stats(nic_dev, &nic_dev->rxqs[i]); ++ gather_rx_stats(nic_rx_stats, &nic_dev->rxqs[i]); + + for (i = 0; i < num_qps; i++) +- update_tx_stats(nic_dev, &nic_dev->txqs[i]); ++ gather_tx_stats(nic_tx_stats, &nic_dev->txqs[i]); + } + + /** +@@ -560,8 +546,6 @@ int hinic_close(struct net_device *netdev) + netif_carrier_off(netdev); + netif_tx_disable(netdev); + +- update_nic_stats(nic_dev); +- + up(&nic_dev->mgmt_lock); + + if (!HINIC_IS_VF(nic_dev->hwdev->hwif)) +@@ -855,26 +839,19 @@ static void hinic_get_stats64(struct net_device *netdev, + struct rtnl_link_stats64 *stats) + { + struct hinic_dev *nic_dev = netdev_priv(netdev); +- struct hinic_rxq_stats *nic_rx_stats; +- struct hinic_txq_stats *nic_tx_stats; +- +- nic_rx_stats = &nic_dev->rx_stats; +- nic_tx_stats = &nic_dev->tx_stats; +- +- down(&nic_dev->mgmt_lock); ++ struct hinic_rxq_stats nic_rx_stats = {}; ++ struct hinic_txq_stats nic_tx_stats = {}; + + if (nic_dev->flags & HINIC_INTF_UP) +- update_nic_stats(nic_dev); +- +- up(&nic_dev->mgmt_lock); ++ gather_nic_stats(nic_dev, &nic_rx_stats, &nic_tx_stats); + +- stats->rx_bytes = nic_rx_stats->bytes; +- stats->rx_packets = nic_rx_stats->pkts; +- stats->rx_errors = nic_rx_stats->errors; ++ stats->rx_bytes = nic_rx_stats.bytes; ++ stats->rx_packets = nic_rx_stats.pkts; ++ stats->rx_errors = nic_rx_stats.errors; + +- stats->tx_bytes = nic_tx_stats->bytes; +- stats->tx_packets = nic_tx_stats->pkts; +- stats->tx_errors = nic_tx_stats->tx_dropped; ++ stats->tx_bytes = nic_tx_stats.bytes; ++ stats->tx_packets = nic_tx_stats.pkts; ++ stats->tx_errors = nic_tx_stats.tx_dropped; + } + + static int hinic_set_features(struct net_device *netdev, +@@ -1173,8 +1150,6 @@ static void hinic_free_intr_coalesce(struct hinic_dev *nic_dev) + static int nic_dev_init(struct pci_dev *pdev) + { + struct hinic_rx_mode_work *rx_mode_work; +- struct hinic_txq_stats *tx_stats; +- struct hinic_rxq_stats *rx_stats; + struct hinic_dev *nic_dev; + struct net_device *netdev; + struct hinic_hwdev *hwdev; +@@ -1235,15 +1210,8 @@ static int nic_dev_init(struct pci_dev *pdev) + + sema_init(&nic_dev->mgmt_lock, 1); + +- tx_stats = &nic_dev->tx_stats; +- rx_stats = &nic_dev->rx_stats; +- +- u64_stats_init(&tx_stats->syncp); +- u64_stats_init(&rx_stats->syncp); +- +- nic_dev->vlan_bitmap = devm_kzalloc(&pdev->dev, +- VLAN_BITMAP_SIZE(nic_dev), +- GFP_KERNEL); ++ nic_dev->vlan_bitmap = devm_bitmap_zalloc(&pdev->dev, VLAN_N_VID, ++ GFP_KERNEL); + if (!nic_dev->vlan_bitmap) { + err = -ENOMEM; + goto err_vlan_bitmap; +diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.c b/drivers/net/ethernet/huawei/hinic/hinic_rx.c +index fed3b6bc0d763..a102d486c4350 100644 +--- a/drivers/net/ethernet/huawei/hinic/hinic_rx.c ++++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.c +@@ -73,7 +73,6 @@ void hinic_rxq_get_stats(struct hinic_rxq *rxq, struct hinic_rxq_stats *stats) + struct hinic_rxq_stats *rxq_stats = &rxq->rxq_stats; + unsigned int start; + +- u64_stats_update_begin(&stats->syncp); + do { + start = u64_stats_fetch_begin(&rxq_stats->syncp); + stats->pkts = rxq_stats->pkts; +@@ -83,7 +82,6 @@ void hinic_rxq_get_stats(struct hinic_rxq *rxq, struct hinic_rxq_stats *stats) + stats->csum_errors = rxq_stats->csum_errors; + stats->other_errors = rxq_stats->other_errors; + } while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); +- u64_stats_update_end(&stats->syncp); + } + + /** +diff --git a/drivers/net/ethernet/huawei/hinic/hinic_tx.c b/drivers/net/ethernet/huawei/hinic/hinic_tx.c +index a984a7a6dd2e2..d1ea358a1fc06 100644 +--- a/drivers/net/ethernet/huawei/hinic/hinic_tx.c ++++ b/drivers/net/ethernet/huawei/hinic/hinic_tx.c +@@ -97,7 +97,6 @@ void hinic_txq_get_stats(struct hinic_txq *txq, struct hinic_txq_stats *stats) + struct hinic_txq_stats *txq_stats = &txq->txq_stats; + unsigned int start; + +- u64_stats_update_begin(&stats->syncp); + do { + start = u64_stats_fetch_begin(&txq_stats->syncp); + stats->pkts = txq_stats->pkts; +@@ -107,7 +106,6 @@ void hinic_txq_get_stats(struct hinic_txq *txq, struct hinic_txq_stats *stats) + stats->tx_dropped = txq_stats->tx_dropped; + stats->big_frags_pkts = txq_stats->big_frags_pkts; + } while (u64_stats_fetch_retry(&txq_stats->syncp, start)); +- u64_stats_update_end(&stats->syncp); + } + + /** +diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h +index 9a122aea69793..99d2b090a1e61 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf.h ++++ b/drivers/net/ethernet/intel/iavf/iavf.h +@@ -89,6 +89,7 @@ struct iavf_vsi { + #define IAVF_HKEY_ARRAY_SIZE ((IAVF_VFQF_HKEY_MAX_INDEX + 1) * 4) + #define IAVF_HLUT_ARRAY_SIZE ((IAVF_VFQF_HLUT_MAX_INDEX + 1) * 4) + #define IAVF_MBPS_DIVISOR 125000 /* divisor to convert to Mbps */ ++#define IAVF_MBPS_QUANTA 50 + + #define IAVF_VIRTCHNL_VF_RESOURCE_SIZE (sizeof(struct virtchnl_vf_resource) + \ + (IAVF_MAX_VF_VSI * \ +@@ -377,6 +378,11 @@ struct iavf_adapter { + /* lock to protect access to the cloud filter list */ + spinlock_t cloud_filter_list_lock; + u16 num_cloud_filters; ++ /* snapshot of "num_active_queues" before setup_tc for qdisc add ++ * is invoked. This information is useful during qdisc del flow, ++ * to restore correct number of queues ++ */ ++ int orig_num_active_queues; + + #define IAVF_MAX_FDIR_FILTERS 128 /* max allowed Flow Director filters */ + u16 fdir_active_fltr; +diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c +index ca74824d40b85..e2349131a4286 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -2732,6 +2732,7 @@ static int iavf_validate_ch_config(struct iavf_adapter *adapter, + struct tc_mqprio_qopt_offload *mqprio_qopt) + { + u64 total_max_rate = 0; ++ u32 tx_rate_rem = 0; + int i, num_qps = 0; + u64 tx_rate = 0; + int ret = 0; +@@ -2746,12 +2747,32 @@ static int iavf_validate_ch_config(struct iavf_adapter *adapter, + return -EINVAL; + if (mqprio_qopt->min_rate[i]) { + dev_err(&adapter->pdev->dev, +- "Invalid min tx rate (greater than 0) specified\n"); ++ "Invalid min tx rate (greater than 0) specified for TC%d\n", ++ i); + return -EINVAL; + } +- /*convert to Mbps */ ++ ++ /* convert to Mbps */ + tx_rate = div_u64(mqprio_qopt->max_rate[i], + IAVF_MBPS_DIVISOR); ++ ++ if (mqprio_qopt->max_rate[i] && ++ tx_rate < IAVF_MBPS_QUANTA) { ++ dev_err(&adapter->pdev->dev, ++ "Invalid max tx rate for TC%d, minimum %dMbps\n", ++ i, IAVF_MBPS_QUANTA); ++ return -EINVAL; ++ } ++ ++ (void)div_u64_rem(tx_rate, IAVF_MBPS_QUANTA, &tx_rate_rem); ++ ++ if (tx_rate_rem != 0) { ++ dev_err(&adapter->pdev->dev, ++ "Invalid max tx rate for TC%d, not divisible by %d\n", ++ i, IAVF_MBPS_QUANTA); ++ return -EINVAL; ++ } ++ + total_max_rate += tx_rate; + num_qps += mqprio_qopt->qopt.count[i]; + } +@@ -2818,6 +2839,7 @@ static int __iavf_setup_tc(struct net_device *netdev, void *type_data) + netif_tx_disable(netdev); + iavf_del_all_cloud_filters(adapter); + adapter->aq_required = IAVF_FLAG_AQ_DISABLE_CHANNELS; ++ total_qps = adapter->orig_num_active_queues; + goto exit; + } else { + return -EINVAL; +@@ -2861,7 +2883,21 @@ static int __iavf_setup_tc(struct net_device *netdev, void *type_data) + adapter->ch_config.ch_info[i].offset = 0; + } + } ++ ++ /* Take snapshot of original config such as "num_active_queues" ++ * It is used later when delete ADQ flow is exercised, so that ++ * once delete ADQ flow completes, VF shall go back to its ++ * original queue configuration ++ */ ++ ++ adapter->orig_num_active_queues = adapter->num_active_queues; ++ ++ /* Store queue info based on TC so that VF gets configured ++ * with correct number of queues when VF completes ADQ config ++ * flow ++ */ + adapter->ch_config.total_qps = total_qps; ++ + netif_tx_stop_all_queues(netdev); + netif_tx_disable(netdev); + adapter->aq_required |= IAVF_FLAG_AQ_ENABLE_CHANNELS; +@@ -2878,6 +2914,12 @@ static int __iavf_setup_tc(struct net_device *netdev, void *type_data) + } + } + exit: ++ if (test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section)) ++ return 0; ++ ++ netif_set_real_num_rx_queues(netdev, total_qps); ++ netif_set_real_num_tx_queues(netdev, total_qps); ++ + return ret; + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h +index 7204bc86e4741..c22a38e5337b2 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h +@@ -103,7 +103,7 @@ struct page_pool; + #define MLX5E_REQUIRED_WQE_MTTS (MLX5_ALIGN_MTTS(MLX5_MPWRQ_PAGES_PER_WQE + 1)) + #define MLX5E_REQUIRED_MTTS(wqes) (wqes * MLX5E_REQUIRED_WQE_MTTS) + #define MLX5E_MAX_RQ_NUM_MTTS \ +- ((1 << 16) * 2) /* So that MLX5_MTT_OCTW(num_mtts) fits into u16 */ ++ (ALIGN_DOWN(U16_MAX, 4) * 2) /* So that MLX5_MTT_OCTW(num_mtts) fits into u16 */ + #define MLX5E_ORDER2_MAX_PACKET_MTU (order_base_2(10 * 1024)) + #define MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE_MPW \ + (ilog2(MLX5E_MAX_RQ_NUM_MTTS / MLX5E_REQUIRED_WQE_MTTS)) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c +index d93aadbf10da8..90ea78239d402 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c +@@ -16,7 +16,7 @@ static int mlx5e_ktls_add(struct net_device *netdev, struct sock *sk, + struct mlx5_core_dev *mdev = priv->mdev; + int err; + +- if (WARN_ON(!mlx5e_ktls_type_check(mdev, crypto_info))) ++ if (!mlx5e_ktls_type_check(mdev, crypto_info)) + return -EOPNOTSUPP; + + if (direction == TLS_OFFLOAD_CTX_DIR_TX) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c +index 4ed7409942791..5a6606c843edf 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -516,7 +516,7 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx) + + /* Check log_max_qp from HCA caps to set in current profile */ + if (prof->log_max_qp == LOG_MAX_SUPPORTED_QPS) { +- prof->log_max_qp = min_t(u8, 17, MLX5_CAP_GEN_MAX(dev, log_max_qp)); ++ prof->log_max_qp = min_t(u8, 18, MLX5_CAP_GEN_MAX(dev, log_max_qp)); + } else if (MLX5_CAP_GEN_MAX(dev, log_max_qp) < prof->log_max_qp) { + mlx5_core_warn(dev, "log_max_qp value in current profile is %d, changing it to HCA capability limit (%d)\n", + prof->log_max_qp, +diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +index 6ac507ddf09af..781313dbd04f2 100644 +--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c ++++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +@@ -1565,7 +1565,7 @@ static int ionic_set_nic_features(struct ionic_lif *lif, + if ((old_hw_features ^ lif->hw_features) & IONIC_ETH_HW_RX_HASH) + ionic_lif_rss_config(lif, lif->rss_types, NULL, NULL); + +- if ((vlan_flags & features) && ++ if ((vlan_flags & le64_to_cpu(ctx.cmd.lif_setattr.features)) && + !(vlan_flags & le64_to_cpu(ctx.comp.lif_setattr.features))) + dev_info_once(lif->ionic->dev, "NIC is not supporting vlan offload, likely in SmartNIC mode\n"); + +diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c +index a438202129323..50854265864d1 100644 +--- a/drivers/net/netdevsim/bpf.c ++++ b/drivers/net/netdevsim/bpf.c +@@ -351,10 +351,12 @@ nsim_map_alloc_elem(struct bpf_offloaded_map *offmap, unsigned int idx) + { + struct nsim_bpf_bound_map *nmap = offmap->dev_priv; + +- nmap->entry[idx].key = kmalloc(offmap->map.key_size, GFP_USER); ++ nmap->entry[idx].key = kmalloc(offmap->map.key_size, ++ GFP_KERNEL_ACCOUNT | __GFP_NOWARN); + if (!nmap->entry[idx].key) + return -ENOMEM; +- nmap->entry[idx].value = kmalloc(offmap->map.value_size, GFP_USER); ++ nmap->entry[idx].value = kmalloc(offmap->map.value_size, ++ GFP_KERNEL_ACCOUNT | __GFP_NOWARN); + if (!nmap->entry[idx].value) { + kfree(nmap->entry[idx].key); + nmap->entry[idx].key = NULL; +@@ -496,7 +498,7 @@ nsim_bpf_map_alloc(struct netdevsim *ns, struct bpf_offloaded_map *offmap) + if (offmap->map.map_flags) + return -EINVAL; + +- nmap = kzalloc(sizeof(*nmap), GFP_USER); ++ nmap = kzalloc(sizeof(*nmap), GFP_KERNEL_ACCOUNT); + if (!nmap) + return -ENOMEM; + +diff --git a/drivers/net/netdevsim/fib.c b/drivers/net/netdevsim/fib.c +index 378ee779061c3..14787d17f703f 100644 +--- a/drivers/net/netdevsim/fib.c ++++ b/drivers/net/netdevsim/fib.c +@@ -53,6 +53,7 @@ struct nsim_fib_data { + struct rhashtable nexthop_ht; + struct devlink *devlink; + struct work_struct fib_event_work; ++ struct work_struct fib_flush_work; + struct list_head fib_event_queue; + spinlock_t fib_event_queue_lock; /* Protects fib event queue list */ + struct mutex nh_lock; /* Protects NH HT */ +@@ -977,7 +978,7 @@ static int nsim_fib_event_schedule_work(struct nsim_fib_data *data, + + fib_event = kzalloc(sizeof(*fib_event), GFP_ATOMIC); + if (!fib_event) +- return NOTIFY_BAD; ++ goto err_fib_event_alloc; + + fib_event->data = data; + fib_event->event = event; +@@ -1005,6 +1006,9 @@ static int nsim_fib_event_schedule_work(struct nsim_fib_data *data, + + err_fib_prepare_event: + kfree(fib_event); ++err_fib_event_alloc: ++ if (event == FIB_EVENT_ENTRY_DEL) ++ schedule_work(&data->fib_flush_work); + return NOTIFY_BAD; + } + +@@ -1482,6 +1486,24 @@ static void nsim_fib_event_work(struct work_struct *work) + mutex_unlock(&data->fib_lock); + } + ++static void nsim_fib_flush_work(struct work_struct *work) ++{ ++ struct nsim_fib_data *data = container_of(work, struct nsim_fib_data, ++ fib_flush_work); ++ struct nsim_fib_rt *fib_rt, *fib_rt_tmp; ++ ++ /* Process pending work. */ ++ flush_work(&data->fib_event_work); ++ ++ mutex_lock(&data->fib_lock); ++ list_for_each_entry_safe(fib_rt, fib_rt_tmp, &data->fib_rt_list, list) { ++ rhashtable_remove_fast(&data->fib_rt_ht, &fib_rt->ht_node, ++ nsim_fib_rt_ht_params); ++ nsim_fib_rt_free(fib_rt, data); ++ } ++ mutex_unlock(&data->fib_lock); ++} ++ + static int + nsim_fib_debugfs_init(struct nsim_fib_data *data, struct nsim_dev *nsim_dev) + { +@@ -1540,6 +1562,7 @@ struct nsim_fib_data *nsim_fib_create(struct devlink *devlink, + goto err_rhashtable_nexthop_destroy; + + INIT_WORK(&data->fib_event_work, nsim_fib_event_work); ++ INIT_WORK(&data->fib_flush_work, nsim_fib_flush_work); + INIT_LIST_HEAD(&data->fib_event_queue); + spin_lock_init(&data->fib_event_queue_lock); + +@@ -1586,6 +1609,7 @@ struct nsim_fib_data *nsim_fib_create(struct devlink *devlink, + err_nexthop_nb_unregister: + unregister_nexthop_notifier(devlink_net(devlink), &data->nexthop_nb); + err_rhashtable_fib_destroy: ++ cancel_work_sync(&data->fib_flush_work); + flush_work(&data->fib_event_work); + rhashtable_free_and_destroy(&data->fib_rt_ht, nsim_fib_rt_free, + data); +@@ -1615,6 +1639,7 @@ void nsim_fib_destroy(struct devlink *devlink, struct nsim_fib_data *data) + NSIM_RESOURCE_IPV4_FIB); + unregister_fib_notifier(devlink_net(devlink), &data->fib_nb); + unregister_nexthop_notifier(devlink_net(devlink), &data->nexthop_nb); ++ cancel_work_sync(&data->fib_flush_work); + flush_work(&data->fib_event_work); + rhashtable_free_and_destroy(&data->fib_rt_ht, nsim_fib_rt_free, + data); +diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c +index d8cac02a79b95..636b0907a5987 100644 +--- a/drivers/net/phy/smsc.c ++++ b/drivers/net/phy/smsc.c +@@ -110,7 +110,7 @@ static int smsc_phy_config_init(struct phy_device *phydev) + struct smsc_phy_priv *priv = phydev->priv; + int rc; + +- if (!priv->energy_enable) ++ if (!priv->energy_enable || phydev->irq != PHY_POLL) + return 0; + + rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); +@@ -210,6 +210,8 @@ static int lan95xx_config_aneg_ext(struct phy_device *phydev) + * response on link pulses to detect presence of plugged Ethernet cable. + * The Energy Detect Power-Down mode is enabled again in the end of procedure to + * save approximately 220 mW of power if cable is unplugged. ++ * The workaround is only applicable to poll mode. Energy Detect Power-Down may ++ * not be used in interrupt mode lest link change detection becomes unreliable. + */ + static int lan87xx_read_status(struct phy_device *phydev) + { +@@ -217,7 +219,7 @@ static int lan87xx_read_status(struct phy_device *phydev) + + int err = genphy_read_status(phydev); + +- if (!phydev->link && priv->energy_enable) { ++ if (!phydev->link && priv->energy_enable && phydev->irq == PHY_POLL) { + /* Disable EDPD to wake up PHY */ + int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); + if (rc < 0) +diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig +index b554054a7560a..8939e5fbd50a8 100644 +--- a/drivers/net/usb/Kconfig ++++ b/drivers/net/usb/Kconfig +@@ -636,8 +636,9 @@ config USB_NET_AQC111 + * Aquantia AQtion USB to 5GbE + + config USB_RTL8153_ECM +- tristate "RTL8153 ECM support" ++ tristate + depends on USB_NET_CDCETHER && (USB_RTL8152 || USB_RTL8152=n) ++ default y + help + This option supports ECM mode for RTL8153 ethernet adapter, when + CONFIG_USB_RTL8152 is not set, or the RTL8153 device is not +diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c +index e1b9b78b474e9..0a2c3860179e7 100644 +--- a/drivers/net/usb/ax88179_178a.c ++++ b/drivers/net/usb/ax88179_178a.c +@@ -1796,7 +1796,7 @@ static const struct driver_info ax88179_info = { + .link_reset = ax88179_link_reset, + .reset = ax88179_reset, + .stop = ax88179_stop, +- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP, ++ .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, + .tx_fixup = ax88179_tx_fixup, + }; +@@ -1809,7 +1809,7 @@ static const struct driver_info ax88178a_info = { + .link_reset = ax88179_link_reset, + .reset = ax88179_reset, + .stop = ax88179_stop, +- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP, ++ .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, + .tx_fixup = ax88179_tx_fixup, + }; +@@ -1822,7 +1822,7 @@ static const struct driver_info cypress_GX3_info = { + .link_reset = ax88179_link_reset, + .reset = ax88179_reset, + .stop = ax88179_stop, +- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP, ++ .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, + .tx_fixup = ax88179_tx_fixup, + }; +@@ -1835,7 +1835,7 @@ static const struct driver_info dlink_dub1312_info = { + .link_reset = ax88179_link_reset, + .reset = ax88179_reset, + .stop = ax88179_stop, +- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP, ++ .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, + .tx_fixup = ax88179_tx_fixup, + }; +@@ -1848,7 +1848,7 @@ static const struct driver_info sitecom_info = { + .link_reset = ax88179_link_reset, + .reset = ax88179_reset, + .stop = ax88179_stop, +- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP, ++ .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, + .tx_fixup = ax88179_tx_fixup, + }; +@@ -1861,7 +1861,7 @@ static const struct driver_info samsung_info = { + .link_reset = ax88179_link_reset, + .reset = ax88179_reset, + .stop = ax88179_stop, +- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP, ++ .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, + .tx_fixup = ax88179_tx_fixup, + }; +@@ -1874,7 +1874,7 @@ static const struct driver_info lenovo_info = { + .link_reset = ax88179_link_reset, + .reset = ax88179_reset, + .stop = ax88179_stop, +- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP, ++ .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, + .tx_fixup = ax88179_tx_fixup, + }; +@@ -1887,7 +1887,7 @@ static const struct driver_info belkin_info = { + .link_reset = ax88179_link_reset, + .reset = ax88179_reset, + .stop = ax88179_stop, +- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP, ++ .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, + .tx_fixup = ax88179_tx_fixup, + }; +@@ -1900,7 +1900,7 @@ static const struct driver_info toshiba_info = { + .link_reset = ax88179_link_reset, + .reset = ax88179_reset, + .stop = ax88179_stop, +- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP, ++ .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, + .tx_fixup = ax88179_tx_fixup, + }; +@@ -1913,7 +1913,7 @@ static const struct driver_info mct_info = { + .link_reset = ax88179_link_reset, + .reset = ax88179_reset, + .stop = ax88179_stop, +- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP, ++ .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, + .tx_fixup = ax88179_tx_fixup, + }; +diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c +index 4e39e43450848..460e90eb528f8 100644 +--- a/drivers/net/usb/smsc95xx.c ++++ b/drivers/net/usb/smsc95xx.c +@@ -18,6 +18,8 @@ + #include <linux/usb/usbnet.h> + #include <linux/slab.h> + #include <linux/of_net.h> ++#include <linux/irq.h> ++#include <linux/irqdomain.h> + #include <linux/mdio.h> + #include <linux/phy.h> + #include "smsc95xx.h" +@@ -51,6 +53,9 @@ + #define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \ + SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3) + ++#define SMSC95XX_NR_IRQS (1) /* raise to 12 for GPIOs */ ++#define PHY_HWIRQ (SMSC95XX_NR_IRQS - 1) ++ + struct smsc95xx_priv { + u32 mac_cr; + u32 hash_hi; +@@ -59,8 +64,12 @@ struct smsc95xx_priv { + spinlock_t mac_cr_lock; + u8 features; + u8 suspend_flags; ++ struct irq_chip irqchip; ++ struct irq_domain *irqdomain; ++ struct fwnode_handle *irqfwnode; + struct mii_bus *mdiobus; + struct phy_device *phydev; ++ struct task_struct *pm_task; + }; + + static bool turbo_mode = true; +@@ -70,13 +79,14 @@ MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); + static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, + u32 *data, int in_pm) + { ++ struct smsc95xx_priv *pdata = dev->driver_priv; + u32 buf; + int ret; + int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16); + + BUG_ON(!dev); + +- if (!in_pm) ++ if (current != pdata->pm_task) + fn = usbnet_read_cmd; + else + fn = usbnet_read_cmd_nopm; +@@ -100,13 +110,14 @@ static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, + static int __must_check __smsc95xx_write_reg(struct usbnet *dev, u32 index, + u32 data, int in_pm) + { ++ struct smsc95xx_priv *pdata = dev->driver_priv; + u32 buf; + int ret; + int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16); + + BUG_ON(!dev); + +- if (!in_pm) ++ if (current != pdata->pm_task) + fn = usbnet_write_cmd; + else + fn = usbnet_write_cmd_nopm; +@@ -564,16 +575,12 @@ static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev) + return smsc95xx_write_reg(dev, AFC_CFG, afc_cfg); + } + +-static int smsc95xx_link_reset(struct usbnet *dev) ++static void smsc95xx_mac_update_fullduplex(struct usbnet *dev) + { + struct smsc95xx_priv *pdata = dev->driver_priv; + unsigned long flags; + int ret; + +- ret = smsc95xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_); +- if (ret < 0) +- return ret; +- + spin_lock_irqsave(&pdata->mac_cr_lock, flags); + if (pdata->phydev->duplex != DUPLEX_FULL) { + pdata->mac_cr &= ~MAC_CR_FDPX_; +@@ -585,18 +592,22 @@ static int smsc95xx_link_reset(struct usbnet *dev) + spin_unlock_irqrestore(&pdata->mac_cr_lock, flags); + + ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr); +- if (ret < 0) +- return ret; ++ if (ret < 0) { ++ if (ret != -ENODEV) ++ netdev_warn(dev->net, ++ "Error updating MAC full duplex mode\n"); ++ return; ++ } + + ret = smsc95xx_phy_update_flowcontrol(dev); + if (ret < 0) + netdev_warn(dev->net, "Error updating PHY flow control\n"); +- +- return ret; + } + + static void smsc95xx_status(struct usbnet *dev, struct urb *urb) + { ++ struct smsc95xx_priv *pdata = dev->driver_priv; ++ unsigned long flags; + u32 intdata; + + if (urb->actual_length != 4) { +@@ -608,11 +619,15 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb) + intdata = get_unaligned_le32(urb->transfer_buffer); + netif_dbg(dev, link, dev->net, "intdata: 0x%08X\n", intdata); + ++ local_irq_save(flags); ++ + if (intdata & INT_ENP_PHY_INT_) +- usbnet_defer_kevent(dev, EVENT_LINK_RESET); ++ generic_handle_domain_irq(pdata->irqdomain, PHY_HWIRQ); + else + netdev_warn(dev->net, "unexpected interrupt, intdata=0x%08X\n", + intdata); ++ ++ local_irq_restore(flags); + } + + /* Enable or disable Tx & Rx checksum offload engines */ +@@ -1066,6 +1081,7 @@ static void smsc95xx_handle_link_change(struct net_device *net) + struct usbnet *dev = netdev_priv(net); + + phy_print_status(net->phydev); ++ smsc95xx_mac_update_fullduplex(dev); + usbnet_defer_kevent(dev, EVENT_LINK_CHANGE); + } + +@@ -1073,8 +1089,9 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) + { + struct smsc95xx_priv *pdata; + bool is_internal_phy; ++ char usb_path[64]; ++ int ret, phy_irq; + u32 val; +- int ret; + + printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n"); + +@@ -1114,10 +1131,38 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) + if (ret) + goto free_pdata; + ++ /* create irq domain for use by PHY driver and GPIO consumers */ ++ usb_make_path(dev->udev, usb_path, sizeof(usb_path)); ++ pdata->irqfwnode = irq_domain_alloc_named_fwnode(usb_path); ++ if (!pdata->irqfwnode) { ++ ret = -ENOMEM; ++ goto free_pdata; ++ } ++ ++ pdata->irqdomain = irq_domain_create_linear(pdata->irqfwnode, ++ SMSC95XX_NR_IRQS, ++ &irq_domain_simple_ops, ++ pdata); ++ if (!pdata->irqdomain) { ++ ret = -ENOMEM; ++ goto free_irqfwnode; ++ } ++ ++ phy_irq = irq_create_mapping(pdata->irqdomain, PHY_HWIRQ); ++ if (!phy_irq) { ++ ret = -ENOENT; ++ goto remove_irqdomain; ++ } ++ ++ pdata->irqchip = dummy_irq_chip; ++ pdata->irqchip.name = SMSC_CHIPNAME; ++ irq_set_chip_and_handler_name(phy_irq, &pdata->irqchip, ++ handle_simple_irq, "phy"); ++ + pdata->mdiobus = mdiobus_alloc(); + if (!pdata->mdiobus) { + ret = -ENOMEM; +- goto free_pdata; ++ goto dispose_irq; + } + + ret = smsc95xx_read_reg(dev, HW_CFG, &val); +@@ -1150,6 +1195,7 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) + goto unregister_mdio; + } + ++ pdata->phydev->irq = phy_irq; + pdata->phydev->is_internal = is_internal_phy; + + /* detect device revision as different features may be available */ +@@ -1192,6 +1238,15 @@ unregister_mdio: + free_mdio: + mdiobus_free(pdata->mdiobus); + ++dispose_irq: ++ irq_dispose_mapping(phy_irq); ++ ++remove_irqdomain: ++ irq_domain_remove(pdata->irqdomain); ++ ++free_irqfwnode: ++ irq_domain_free_fwnode(pdata->irqfwnode); ++ + free_pdata: + kfree(pdata); + return ret; +@@ -1204,6 +1259,9 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf) + phy_disconnect(dev->net->phydev); + mdiobus_unregister(pdata->mdiobus); + mdiobus_free(pdata->mdiobus); ++ irq_dispose_mapping(irq_find_mapping(pdata->irqdomain, PHY_HWIRQ)); ++ irq_domain_remove(pdata->irqdomain); ++ irq_domain_free_fwnode(pdata->irqfwnode); + netif_dbg(dev, ifdown, dev->net, "free pdata\n"); + kfree(pdata); + } +@@ -1228,29 +1286,6 @@ static u32 smsc_crc(const u8 *buffer, size_t len, int filter) + return crc << ((filter % 2) * 16); + } + +-static int smsc95xx_enable_phy_wakeup_interrupts(struct usbnet *dev, u16 mask) +-{ +- int ret; +- +- netdev_dbg(dev->net, "enabling PHY wakeup interrupts\n"); +- +- /* read to clear */ +- ret = smsc95xx_mdio_read_nopm(dev, PHY_INT_SRC); +- if (ret < 0) +- return ret; +- +- /* enable interrupt source */ +- ret = smsc95xx_mdio_read_nopm(dev, PHY_INT_MASK); +- if (ret < 0) +- return ret; +- +- ret |= mask; +- +- smsc95xx_mdio_write_nopm(dev, PHY_INT_MASK, ret); +- +- return 0; +-} +- + static int smsc95xx_link_ok_nopm(struct usbnet *dev) + { + int ret; +@@ -1417,7 +1452,6 @@ static int smsc95xx_enter_suspend3(struct usbnet *dev) + static int smsc95xx_autosuspend(struct usbnet *dev, u32 link_up) + { + struct smsc95xx_priv *pdata = dev->driver_priv; +- int ret; + + if (!netif_running(dev->net)) { + /* interface is ifconfig down so fully power down hw */ +@@ -1436,27 +1470,10 @@ static int smsc95xx_autosuspend(struct usbnet *dev, u32 link_up) + } + + netdev_dbg(dev->net, "autosuspend entering SUSPEND1\n"); +- +- /* enable PHY wakeup events for if cable is attached */ +- ret = smsc95xx_enable_phy_wakeup_interrupts(dev, +- PHY_INT_MASK_ANEG_COMP_); +- if (ret < 0) { +- netdev_warn(dev->net, "error enabling PHY wakeup ints\n"); +- return ret; +- } +- + netdev_info(dev->net, "entering SUSPEND1 mode\n"); + return smsc95xx_enter_suspend1(dev); + } + +- /* enable PHY wakeup events so we remote wakeup if cable is pulled */ +- ret = smsc95xx_enable_phy_wakeup_interrupts(dev, +- PHY_INT_MASK_LINK_DOWN_); +- if (ret < 0) { +- netdev_warn(dev->net, "error enabling PHY wakeup ints\n"); +- return ret; +- } +- + netdev_dbg(dev->net, "autosuspend entering SUSPEND3\n"); + return smsc95xx_enter_suspend3(dev); + } +@@ -1468,9 +1485,12 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message) + u32 val, link_up; + int ret; + ++ pdata->pm_task = current; ++ + ret = usbnet_suspend(intf, message); + if (ret < 0) { + netdev_warn(dev->net, "usbnet_suspend error\n"); ++ pdata->pm_task = NULL; + return ret; + } + +@@ -1522,13 +1542,6 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message) + } + + if (pdata->wolopts & WAKE_PHY) { +- ret = smsc95xx_enable_phy_wakeup_interrupts(dev, +- (PHY_INT_MASK_ANEG_COMP_ | PHY_INT_MASK_LINK_DOWN_)); +- if (ret < 0) { +- netdev_warn(dev->net, "error enabling PHY wakeup ints\n"); +- goto done; +- } +- + /* if link is down then configure EDPD and enter SUSPEND1, + * otherwise enter SUSPEND0 below + */ +@@ -1717,6 +1730,7 @@ done: + if (ret && PMSG_IS_AUTO(message)) + usbnet_resume(intf); + ++ pdata->pm_task = NULL; + return ret; + } + +@@ -1737,45 +1751,53 @@ static int smsc95xx_resume(struct usb_interface *intf) + /* do this first to ensure it's cleared even in error case */ + pdata->suspend_flags = 0; + ++ pdata->pm_task = current; ++ + if (suspend_flags & SUSPEND_ALLMODES) { + /* clear wake-up sources */ + ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val); + if (ret < 0) +- return ret; ++ goto done; + + val &= ~(WUCSR_WAKE_EN_ | WUCSR_MPEN_); + + ret = smsc95xx_write_reg_nopm(dev, WUCSR, val); + if (ret < 0) +- return ret; ++ goto done; + + /* clear wake-up status */ + ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val); + if (ret < 0) +- return ret; ++ goto done; + + val &= ~PM_CTL_WOL_EN_; + val |= PM_CTL_WUPS_; + + ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val); + if (ret < 0) +- return ret; ++ goto done; + } + ++ phy_init_hw(pdata->phydev); ++ + ret = usbnet_resume(intf); + if (ret < 0) + netdev_warn(dev->net, "usbnet_resume error\n"); + +- phy_init_hw(pdata->phydev); ++done: ++ pdata->pm_task = NULL; + return ret; + } + + static int smsc95xx_reset_resume(struct usb_interface *intf) + { + struct usbnet *dev = usb_get_intfdata(intf); ++ struct smsc95xx_priv *pdata = dev->driver_priv; + int ret; + ++ pdata->pm_task = current; + ret = smsc95xx_reset(dev); ++ pdata->pm_task = NULL; + if (ret < 0) + return ret; + +@@ -1971,7 +1993,6 @@ static const struct driver_info smsc95xx_info = { + .description = "smsc95xx USB 2.0 Ethernet", + .bind = smsc95xx_bind, + .unbind = smsc95xx_unbind, +- .link_reset = smsc95xx_link_reset, + .reset = smsc95xx_reset, + .check_connect = smsc95xx_start_phy, + .stop = smsc95xx_stop, +diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c +index 71bb0849ce480..5b7272fd25ee8 100644 +--- a/drivers/net/usb/usbnet.c ++++ b/drivers/net/usb/usbnet.c +@@ -847,13 +847,11 @@ int usbnet_stop (struct net_device *net) + + mpn = !test_and_clear_bit(EVENT_NO_RUNTIME_PM, &dev->flags); + +- /* deferred work (task, timer, softirq) must also stop. +- * can't flush_scheduled_work() until we drop rtnl (later), +- * else workers could deadlock; so make workers a NOP. +- */ ++ /* deferred work (timer, softirq, task) must also stop */ + dev->flags = 0; + del_timer_sync (&dev->delay); + tasklet_kill (&dev->bh); ++ cancel_work_sync(&dev->kevent); + if (!pm) + usb_autopm_put_interface(dev->intf); + +@@ -1617,8 +1615,6 @@ void usbnet_disconnect (struct usb_interface *intf) + net = dev->net; + unregister_netdev (net); + +- cancel_work_sync(&dev->kevent); +- + usb_scuttle_anchored_urbs(&dev->deferred); + + if (dev->driver_info->unbind) +diff --git a/drivers/net/wireguard/allowedips.c b/drivers/net/wireguard/allowedips.c +index 9a4c8ff32d9dd..5bf7822c53f18 100644 +--- a/drivers/net/wireguard/allowedips.c ++++ b/drivers/net/wireguard/allowedips.c +@@ -6,6 +6,8 @@ + #include "allowedips.h" + #include "peer.h" + ++enum { MAX_ALLOWEDIPS_BITS = 128 }; ++ + static struct kmem_cache *node_cache; + + static void swap_endian(u8 *dst, const u8 *src, u8 bits) +@@ -40,7 +42,8 @@ static void push_rcu(struct allowedips_node **stack, + struct allowedips_node __rcu *p, unsigned int *len) + { + if (rcu_access_pointer(p)) { +- WARN_ON(IS_ENABLED(DEBUG) && *len >= 128); ++ if (WARN_ON(IS_ENABLED(DEBUG) && *len >= MAX_ALLOWEDIPS_BITS)) ++ return; + stack[(*len)++] = rcu_dereference_raw(p); + } + } +@@ -52,7 +55,7 @@ static void node_free_rcu(struct rcu_head *rcu) + + static void root_free_rcu(struct rcu_head *rcu) + { +- struct allowedips_node *node, *stack[128] = { ++ struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_BITS] = { + container_of(rcu, struct allowedips_node, rcu) }; + unsigned int len = 1; + +@@ -65,7 +68,7 @@ static void root_free_rcu(struct rcu_head *rcu) + + static void root_remove_peer_lists(struct allowedips_node *root) + { +- struct allowedips_node *node, *stack[128] = { root }; ++ struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_BITS] = { root }; + unsigned int len = 1; + + while (len > 0 && (node = stack[--len])) { +diff --git a/drivers/net/wireguard/selftest/allowedips.c b/drivers/net/wireguard/selftest/allowedips.c +index e173204ae7d78..41db10f9be498 100644 +--- a/drivers/net/wireguard/selftest/allowedips.c ++++ b/drivers/net/wireguard/selftest/allowedips.c +@@ -593,10 +593,10 @@ bool __init wg_allowedips_selftest(void) + wg_allowedips_remove_by_peer(&t, a, &mutex); + test_negative(4, a, 192, 168, 0, 1); + +- /* These will hit the WARN_ON(len >= 128) in free_node if something +- * goes wrong. ++ /* These will hit the WARN_ON(len >= MAX_ALLOWEDIPS_BITS) in free_node ++ * if something goes wrong. + */ +- for (i = 0; i < 128; ++i) { ++ for (i = 0; i < MAX_ALLOWEDIPS_BITS; ++i) { + part = cpu_to_be64(~(1LLU << (i % 64))); + memset(&ip, 0xff, 16); + memcpy((u8 *)&ip + (i < 64) * 8, &part, 8); +diff --git a/drivers/net/wireguard/selftest/ratelimiter.c b/drivers/net/wireguard/selftest/ratelimiter.c +index 007cd4457c5f6..ba87d294604fe 100644 +--- a/drivers/net/wireguard/selftest/ratelimiter.c ++++ b/drivers/net/wireguard/selftest/ratelimiter.c +@@ -6,28 +6,29 @@ + #ifdef DEBUG + + #include <linux/jiffies.h> ++#include <linux/hrtimer.h> + + static const struct { + bool result; +- unsigned int msec_to_sleep_before; ++ u64 nsec_to_sleep_before; + } expected_results[] __initconst = { + [0 ... PACKETS_BURSTABLE - 1] = { true, 0 }, + [PACKETS_BURSTABLE] = { false, 0 }, +- [PACKETS_BURSTABLE + 1] = { true, MSEC_PER_SEC / PACKETS_PER_SECOND }, ++ [PACKETS_BURSTABLE + 1] = { true, NSEC_PER_SEC / PACKETS_PER_SECOND }, + [PACKETS_BURSTABLE + 2] = { false, 0 }, +- [PACKETS_BURSTABLE + 3] = { true, (MSEC_PER_SEC / PACKETS_PER_SECOND) * 2 }, ++ [PACKETS_BURSTABLE + 3] = { true, (NSEC_PER_SEC / PACKETS_PER_SECOND) * 2 }, + [PACKETS_BURSTABLE + 4] = { true, 0 }, + [PACKETS_BURSTABLE + 5] = { false, 0 } + }; + + static __init unsigned int maximum_jiffies_at_index(int index) + { +- unsigned int total_msecs = 2 * MSEC_PER_SEC / PACKETS_PER_SECOND / 3; ++ u64 total_nsecs = 2 * NSEC_PER_SEC / PACKETS_PER_SECOND / 3; + int i; + + for (i = 0; i <= index; ++i) +- total_msecs += expected_results[i].msec_to_sleep_before; +- return msecs_to_jiffies(total_msecs); ++ total_nsecs += expected_results[i].nsec_to_sleep_before; ++ return nsecs_to_jiffies(total_nsecs); + } + + static __init int timings_test(struct sk_buff *skb4, struct iphdr *hdr4, +@@ -42,8 +43,12 @@ static __init int timings_test(struct sk_buff *skb4, struct iphdr *hdr4, + loop_start_time = jiffies; + + for (i = 0; i < ARRAY_SIZE(expected_results); ++i) { +- if (expected_results[i].msec_to_sleep_before) +- msleep(expected_results[i].msec_to_sleep_before); ++ if (expected_results[i].nsec_to_sleep_before) { ++ ktime_t timeout = ktime_add(ktime_add_ns(ktime_get_coarse_boottime(), TICK_NSEC * 4 / 3), ++ ns_to_ktime(expected_results[i].nsec_to_sleep_before)); ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ schedule_hrtimeout_range_clock(&timeout, 0, HRTIMER_MODE_ABS, CLOCK_BOOTTIME); ++ } + + if (time_is_before_jiffies(loop_start_time + + maximum_jiffies_at_index(i))) +@@ -127,7 +132,7 @@ bool __init wg_ratelimiter_selftest(void) + if (IS_ENABLED(CONFIG_KASAN) || IS_ENABLED(CONFIG_UBSAN)) + return true; + +- BUILD_BUG_ON(MSEC_PER_SEC % PACKETS_PER_SECOND != 0); ++ BUILD_BUG_ON(NSEC_PER_SEC % PACKETS_PER_SECOND != 0); + + if (wg_ratelimiter_init()) + goto out; +@@ -176,7 +181,6 @@ bool __init wg_ratelimiter_selftest(void) + test += test_count; + goto err; + } +- msleep(500); + continue; + } else if (ret < 0) { + test += test_count; +@@ -195,7 +199,6 @@ bool __init wg_ratelimiter_selftest(void) + test += test_count; + goto err; + } +- msleep(50); + continue; + } + test += test_count; +diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c +index f79dd9a716906..73fe77e7824b4 100644 +--- a/drivers/net/wireless/ath/ath10k/snoc.c ++++ b/drivers/net/wireless/ath/ath10k/snoc.c +@@ -1249,13 +1249,12 @@ static void ath10k_snoc_init_napi(struct ath10k *ar) + static int ath10k_snoc_request_irq(struct ath10k *ar) + { + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); +- int irqflags = IRQF_TRIGGER_RISING; + int ret, id; + + for (id = 0; id < CE_COUNT_MAX; id++) { + ret = request_irq(ar_snoc->ce_irqs[id].irq_line, +- ath10k_snoc_per_engine_handler, +- irqflags, ce_name[id], ar); ++ ath10k_snoc_per_engine_handler, 0, ++ ce_name[id], ar); + if (ret) { + ath10k_err(ar, + "failed to register IRQ handler for CE %d: %d\n", +diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c +index 48b4151e13a3e..48a449fbd2bcc 100644 +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -699,23 +699,23 @@ static int ath11k_core_pdev_create(struct ath11k_base *ab) + return ret; + } + +- ret = ath11k_mac_register(ab); ++ ret = ath11k_dp_pdev_alloc(ab); + if (ret) { +- ath11k_err(ab, "failed register the radio with mac80211: %d\n", ret); ++ ath11k_err(ab, "failed to attach DP pdev: %d\n", ret); + goto err_pdev_debug; + } + +- ret = ath11k_dp_pdev_alloc(ab); ++ ret = ath11k_mac_register(ab); + if (ret) { +- ath11k_err(ab, "failed to attach DP pdev: %d\n", ret); +- goto err_mac_unregister; ++ ath11k_err(ab, "failed register the radio with mac80211: %d\n", ret); ++ goto err_dp_pdev_free; + } + + ret = ath11k_thermal_register(ab); + if (ret) { + ath11k_err(ab, "could not register thermal device: %d\n", + ret); +- goto err_dp_pdev_free; ++ goto err_mac_unregister; + } + + ret = ath11k_spectral_init(ab); +@@ -728,10 +728,10 @@ static int ath11k_core_pdev_create(struct ath11k_base *ab) + + err_thermal_unregister: + ath11k_thermal_unregister(ab); +-err_dp_pdev_free: +- ath11k_dp_pdev_free(ab); + err_mac_unregister: + ath11k_mac_unregister(ab); ++err_dp_pdev_free: ++ ath11k_dp_pdev_free(ab); + err_pdev_debug: + ath11k_debugfs_pdev_destroy(ab); + +diff --git a/drivers/net/wireless/ath/ath11k/debug.h b/drivers/net/wireless/ath/ath11k/debug.h +index 659a275e2eb38..694ebba17fad7 100644 +--- a/drivers/net/wireless/ath/ath11k/debug.h ++++ b/drivers/net/wireless/ath/ath11k/debug.h +@@ -23,8 +23,8 @@ enum ath11k_debug_mask { + ATH11K_DBG_TESTMODE = 0x00000400, + ATH11k_DBG_HAL = 0x00000800, + ATH11K_DBG_PCI = 0x00001000, +- ATH11K_DBG_DP_TX = 0x00001000, +- ATH11K_DBG_DP_RX = 0x00002000, ++ ATH11K_DBG_DP_TX = 0x00002000, ++ ATH11K_DBG_DP_RX = 0x00004000, + ATH11K_DBG_ANY = 0xffffffff, + }; + +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index f85fd341557ea..c7ee373a9d2c9 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -6566,7 +6566,7 @@ static int __ath11k_mac_register(struct ath11k *ar) + ar->hw->queues = ATH11K_HW_MAX_QUEUES; + ar->hw->wiphy->tx_queue_len = ATH11K_QUEUE_LEN; + ar->hw->offchannel_tx_hw_queue = ATH11K_HW_MAX_QUEUES - 1; +- ar->hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; ++ ar->hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; + + ar->hw->vif_data_size = sizeof(struct ath11k_vif); + ar->hw->sta_data_size = sizeof(struct ath11k_sta); +diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h +index 6b45e63fae4ba..e3d546ef71ddc 100644 +--- a/drivers/net/wireless/ath/ath9k/htc.h ++++ b/drivers/net/wireless/ath/ath9k/htc.h +@@ -327,11 +327,11 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb) + } + + #ifdef CONFIG_ATH9K_HTC_DEBUGFS +- +-#define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) +-#define TX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c += a) +-#define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.skbrx_stats.c++) +-#define RX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.skbrx_stats.c += a) ++#define __STAT_SAFE(expr) (hif_dev->htc_handle->drv_priv ? (expr) : 0) ++#define TX_STAT_INC(c) __STAT_SAFE(hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) ++#define TX_STAT_ADD(c, a) __STAT_SAFE(hif_dev->htc_handle->drv_priv->debug.tx_stats.c += a) ++#define RX_STAT_INC(c) __STAT_SAFE(hif_dev->htc_handle->drv_priv->debug.skbrx_stats.c++) ++#define RX_STAT_ADD(c, a) __STAT_SAFE(hif_dev->htc_handle->drv_priv->debug.skbrx_stats.c += a) + #define CAB_STAT_INC priv->debug.tx_stats.cab_queued++ + + #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++) +diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c +index ff61ae34ecdf0..07ac88fb1c577 100644 +--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c ++++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c +@@ -944,7 +944,6 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, + priv->hw = hw; + priv->htc = htc_handle; + priv->dev = dev; +- htc_handle->drv_priv = priv; + SET_IEEE80211_DEV(hw, priv->dev); + + ret = ath9k_htc_wait_for_target(priv); +@@ -965,6 +964,8 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, + if (ret) + goto err_init; + ++ htc_handle->drv_priv = priv; ++ + return 0; + + err_init: +diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c +index 4c944e595978b..ac7787e1a7f61 100644 +--- a/drivers/net/wireless/ath/wil6210/debugfs.c ++++ b/drivers/net/wireless/ath/wil6210/debugfs.c +@@ -1010,20 +1010,14 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf, + void *cmd; + int cmdlen = len - sizeof(struct wmi_cmd_hdr); + u16 cmdid; +- int rc, rc1; ++ int rc1; + +- if (cmdlen < 0) ++ if (cmdlen < 0 || *ppos != 0) + return -EINVAL; + +- wmi = kmalloc(len, GFP_KERNEL); +- if (!wmi) +- return -ENOMEM; +- +- rc = simple_write_to_buffer(wmi, len, ppos, buf, len); +- if (rc < 0) { +- kfree(wmi); +- return rc; +- } ++ wmi = memdup_user(buf, len); ++ if (IS_ERR(wmi)) ++ return PTR_ERR(wmi); + + cmd = (cmdlen > 0) ? &wmi[1] : NULL; + cmdid = le16_to_cpu(wmi->command_id); +@@ -1033,7 +1027,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf, + + wil_info(wil, "0x%04x[%d] -> %d\n", cmdid, cmdlen, rc1); + +- return rc; ++ return len; + } + + static const struct file_operations fops_wmi = { +diff --git a/drivers/net/wireless/intel/iwlegacy/4965-rs.c b/drivers/net/wireless/intel/iwlegacy/4965-rs.c +index 9a491e5db75bd..532e3b91777d9 100644 +--- a/drivers/net/wireless/intel/iwlegacy/4965-rs.c ++++ b/drivers/net/wireless/intel/iwlegacy/4965-rs.c +@@ -2403,7 +2403,7 @@ il4965_rs_fill_link_cmd(struct il_priv *il, struct il_lq_sta *lq_sta, + /* Repeat initial/next rate. + * For legacy IL_NUMBER_TRY == 1, this loop will not execute. + * For HT IL_HT_NUMBER_TRY == 3, this executes twice. */ +- while (repeat_rate > 0 && idx < LINK_QUAL_MAX_RETRY_NUM) { ++ while (repeat_rate > 0) { + if (is_legacy(tbl_type.lq_type)) { + if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE) + ant_toggle_cnt++; +@@ -2422,6 +2422,8 @@ il4965_rs_fill_link_cmd(struct il_priv *il, struct il_lq_sta *lq_sta, + cpu_to_le32(new_rate); + repeat_rate--; + idx++; ++ if (idx >= LINK_QUAL_MAX_RETRY_NUM) ++ goto out; + } + + il4965_rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, +@@ -2466,6 +2468,7 @@ il4965_rs_fill_link_cmd(struct il_priv *il, struct il_lq_sta *lq_sta, + repeat_rate--; + } + ++out: + lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; + lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +index c77d98c888116..eeb81808db088 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +@@ -761,12 +761,12 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, + if (!hw) + return NULL; + +- hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; ++ hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; + + if (cfg->max_tx_agg_size) + hw->max_tx_aggregation_subframes = cfg->max_tx_agg_size; + else +- hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; ++ hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; + + op_mode = hw->priv; + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +index a64874c05cede..1bb456daff9e9 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +@@ -1794,6 +1794,7 @@ static void iwl_mvm_disable_sta_queues(struct iwl_mvm *mvm, + iwl_mvm_txq_from_mac80211(sta->txq[i]); + + mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE; ++ list_del_init(&mvmtxq->list); + } + } + +diff --git a/drivers/net/wireless/intersil/p54/main.c b/drivers/net/wireless/intersil/p54/main.c +index a3ca6620dc0c6..8fa3ec71603e3 100644 +--- a/drivers/net/wireless/intersil/p54/main.c ++++ b/drivers/net/wireless/intersil/p54/main.c +@@ -682,7 +682,7 @@ static void p54_flush(struct ieee80211_hw *dev, struct ieee80211_vif *vif, + * queues have already been stopped and no new frames can sneak + * up from behind. + */ +- while ((total = p54_flush_count(priv) && i--)) { ++ while ((total = p54_flush_count(priv)) && i--) { + /* waste time */ + msleep(20); + } +diff --git a/drivers/net/wireless/intersil/p54/p54spi.c b/drivers/net/wireless/intersil/p54/p54spi.c +index ab0fe85658518..cdb57819684ae 100644 +--- a/drivers/net/wireless/intersil/p54/p54spi.c ++++ b/drivers/net/wireless/intersil/p54/p54spi.c +@@ -164,7 +164,7 @@ static int p54spi_request_firmware(struct ieee80211_hw *dev) + + ret = p54_parse_firmware(dev, priv->firmware); + if (ret) { +- release_firmware(priv->firmware); ++ /* the firmware is released by the caller */ + return ret; + } + +@@ -659,6 +659,7 @@ static int p54spi_probe(struct spi_device *spi) + return 0; + + err_free_common: ++ release_firmware(priv->firmware); + free_irq(gpio_to_irq(p54spi_gpio_irq), spi); + err_free_gpio_irq: + gpio_free(p54spi_gpio_irq); +diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c +index c3189e2c7c93a..feddf4045a8ca 100644 +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -663,7 +663,7 @@ struct mac80211_hwsim_data { + bool ps_poll_pending; + struct dentry *debugfs; + +- uintptr_t pending_cookie; ++ atomic_t pending_cookie; + struct sk_buff_head pending; /* packets pending */ + /* + * Only radios in the same group can communicate together (the +@@ -1339,8 +1339,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, + goto nla_put_failure; + + /* We create a cookie to identify this skb */ +- data->pending_cookie++; +- cookie = data->pending_cookie; ++ cookie = atomic_inc_return(&data->pending_cookie); + info->rate_driver_data[0] = (void *)cookie; + if (nla_put_u64_64bit(skb, HWSIM_ATTR_COOKIE, cookie, HWSIM_ATTR_PAD)) + goto nla_put_failure; +@@ -3582,6 +3581,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2, + const u8 *src; + unsigned int hwsim_flags; + int i; ++ unsigned long flags; + bool found = false; + + if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] || +@@ -3609,18 +3609,20 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2, + } + + /* look for the skb matching the cookie passed back from user */ ++ spin_lock_irqsave(&data2->pending.lock, flags); + skb_queue_walk_safe(&data2->pending, skb, tmp) { +- u64 skb_cookie; ++ uintptr_t skb_cookie; + + txi = IEEE80211_SKB_CB(skb); +- skb_cookie = (u64)(uintptr_t)txi->rate_driver_data[0]; ++ skb_cookie = (uintptr_t)txi->rate_driver_data[0]; + + if (skb_cookie == ret_skb_cookie) { +- skb_unlink(skb, &data2->pending); ++ __skb_unlink(skb, &data2->pending); + found = true; + break; + } + } ++ spin_unlock_irqrestore(&data2->pending.lock, flags); + + /* not found */ + if (!found) +diff --git a/drivers/net/wireless/marvell/libertas/if_usb.c b/drivers/net/wireless/marvell/libertas/if_usb.c +index 5d6dc1dd050d4..32fdc4150b605 100644 +--- a/drivers/net/wireless/marvell/libertas/if_usb.c ++++ b/drivers/net/wireless/marvell/libertas/if_usb.c +@@ -287,6 +287,7 @@ static int if_usb_probe(struct usb_interface *intf, + return 0; + + err_get_fw: ++ usb_put_dev(udev); + lbs_remove_card(priv); + err_add_card: + if_usb_reset_device(cardp); +diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h +index 5923c5c14c8df..f4e3dce10d654 100644 +--- a/drivers/net/wireless/marvell/mwifiex/main.h ++++ b/drivers/net/wireless/marvell/mwifiex/main.h +@@ -1054,6 +1054,8 @@ struct mwifiex_adapter { + void *devdump_data; + int devdump_len; + struct timer_list devdump_timer; ++ ++ bool ignore_btcoex_events; + }; + + void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter); +diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c +index c3f5583ea70df..d5fb29400bad5 100644 +--- a/drivers/net/wireless/marvell/mwifiex/pcie.c ++++ b/drivers/net/wireless/marvell/mwifiex/pcie.c +@@ -3152,6 +3152,9 @@ static int mwifiex_init_pcie(struct mwifiex_adapter *adapter) + if (ret) + goto err_alloc_buffers; + ++ if (pdev->device == PCIE_DEVICE_ID_MARVELL_88W8897) ++ adapter->ignore_btcoex_events = true; ++ + return 0; + + err_alloc_buffers: +diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c +index 2b2e6e0166e14..7d42c5d2dbf65 100644 +--- a/drivers/net/wireless/marvell/mwifiex/sta_event.c ++++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c +@@ -1062,6 +1062,9 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) + break; + case EVENT_BT_COEX_WLAN_PARA_CHANGE: + dev_dbg(adapter->dev, "EVENT: BT coex wlan param update\n"); ++ if (adapter->ignore_btcoex_events) ++ break; ++ + mwifiex_bt_coex_wlan_param_update_event(priv, + adapter->event_skb); + break; +diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c +index 3b47e85e95e7c..db0cd56c8dc7f 100644 +--- a/drivers/net/wireless/mediatek/mt76/eeprom.c ++++ b/drivers/net/wireless/mediatek/mt76/eeprom.c +@@ -146,10 +146,13 @@ mt76_find_power_limits_node(struct mt76_dev *dev) + } + + if (mt76_string_prop_find(country, dev->alpha2) || +- mt76_string_prop_find(regd, region_name)) ++ mt76_string_prop_find(regd, region_name)) { ++ of_node_put(np); + return cur; ++ } + } + ++ of_node_put(np); + return fallback; + } + +diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c +index 029599d68ca71..028519a739fd1 100644 +--- a/drivers/net/wireless/mediatek/mt76/mac80211.c ++++ b/drivers/net/wireless/mediatek/mt76/mac80211.c +@@ -123,6 +123,7 @@ static int mt76_led_init(struct mt76_dev *dev) + if (!of_property_read_u32(np, "led-sources", &led_pin)) + dev->led_pin = led_pin; + dev->led_al = of_property_read_bool(np, "led-active-low"); ++ of_node_put(np); + } + + return led_classdev_register(dev->dev, &dev->led_cdev); +diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +index 4fed3afad67cc..bde65af72feda 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +@@ -385,10 +385,11 @@ static int mt7615_mcu_fw_pmctrl(struct mt7615_dev *dev) + } + + mt7622_trigger_hif_int(dev, false); +- +- pm->stats.last_doze_event = jiffies; +- pm->stats.awake_time += pm->stats.last_doze_event - +- pm->stats.last_wake_event; ++ if (!err) { ++ pm->stats.last_doze_event = jiffies; ++ pm->stats.awake_time += pm->stats.last_doze_event - ++ pm->stats.last_wake_event; ++ } + out: + mutex_unlock(&pm->mutex); + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c +index 2953df7d8388d..c6c16fe8ee859 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c +@@ -108,7 +108,7 @@ __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb, + ret = mt76u_bulk_msg(dev, skb->data, skb->len, NULL, 500, + MT_EP_OUT_INBAND_CMD); + if (ret) +- return ret; ++ goto out; + + if (wait_resp) + ret = mt76x02u_mcu_wait_resp(dev, seq); +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c +index b171027e0cfa8..1ae42ef147c8a 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c +@@ -217,8 +217,8 @@ mt7915_init_wiphy(struct ieee80211_hw *hw) + struct wiphy *wiphy = hw->wiphy; + + hw->queues = 4; +- hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; +- hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; ++ hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; ++ hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; + hw->netdev_features = NETIF_F_RXCSUM; + + hw->radiotap_timestamp.units_pos = +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c +index 78a00028137bd..c059cb419efd8 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c +@@ -49,8 +49,8 @@ mt7921_init_wiphy(struct ieee80211_hw *hw) + struct wiphy *wiphy = hw->wiphy; + + hw->queues = 4; +- hw->max_rx_aggregation_subframes = 64; +- hw->max_tx_aggregation_subframes = 128; ++ hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; ++ hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; + hw->netdev_features = NETIF_F_RXCSUM; + + hw->radiotap_timestamp.units_pos = +@@ -219,7 +219,7 @@ int mt7921_register_device(struct mt7921_dev *dev) + IEEE80211_HT_CAP_LDPC_CODING | + IEEE80211_HT_CAP_MAX_AMSDU; + dev->mphy.sband_5g.sband.vht_cap.cap |= +- IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | ++ IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | + IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | + IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | +diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.c b/drivers/net/wireless/realtek/rtlwifi/debug.c +index 901cdfe3723cf..0b1bc04cb6adb 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/debug.c ++++ b/drivers/net/wireless/realtek/rtlwifi/debug.c +@@ -329,8 +329,8 @@ static ssize_t rtl_debugfs_set_write_h2c(struct file *filp, + + tmp_len = (count > sizeof(tmp) - 1 ? sizeof(tmp) - 1 : count); + +- if (!buffer || copy_from_user(tmp, buffer, tmp_len)) +- return count; ++ if (copy_from_user(tmp, buffer, tmp_len)) ++ return -EFAULT; + + tmp[tmp_len] = '\0'; + +@@ -340,8 +340,8 @@ static ssize_t rtl_debugfs_set_write_h2c(struct file *filp, + &h2c_data[4], &h2c_data[5], + &h2c_data[6], &h2c_data[7]); + +- if (h2c_len <= 0) +- return count; ++ if (h2c_len == 0) ++ return -EINVAL; + + for (i = 0; i < h2c_len; i++) + h2c_data_packed[i] = (u8)h2c_data[i]; +diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c +index 69512856bb462..5786995d90d4d 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.c ++++ b/drivers/net/wireless/realtek/rtw88/main.c +@@ -1819,6 +1819,10 @@ int rtw_core_init(struct rtw_dev *rtwdev) + timer_setup(&rtwdev->tx_report.purge_timer, + rtw_tx_report_purge_timer, 0); + rtwdev->tx_wq = alloc_workqueue("rtw_tx_wq", WQ_UNBOUND | WQ_HIGHPRI, 0); ++ if (!rtwdev->tx_wq) { ++ rtw_warn(rtwdev, "alloc_workqueue rtw_tx_wq failed\n"); ++ return -ENOMEM; ++ } + + INIT_DELAYED_WORK(&rtwdev->watch_dog_work, rtw_watch_dog_work); + INIT_DELAYED_WORK(&coex->bt_relink_work, rtw_coex_bt_relink_work); +diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c +index 0c9cdbaf5cd63..ed2740585c5de 100644 +--- a/drivers/nvme/host/core.c ++++ b/drivers/nvme/host/core.c +@@ -1719,7 +1719,7 @@ static int nvme_setup_streams_ns(struct nvme_ctrl *ctrl, struct nvme_ns *ns, + return 0; + } + +-static int nvme_configure_metadata(struct nvme_ns *ns, struct nvme_id_ns *id) ++static void nvme_configure_metadata(struct nvme_ns *ns, struct nvme_id_ns *id) + { + struct nvme_ctrl *ctrl = ns->ctrl; + +@@ -1735,7 +1735,8 @@ static int nvme_configure_metadata(struct nvme_ns *ns, struct nvme_id_ns *id) + + ns->features &= ~(NVME_NS_METADATA_SUPPORTED | NVME_NS_EXT_LBAS); + if (!ns->ms || !(ctrl->ops->flags & NVME_F_METADATA_SUPPORTED)) +- return 0; ++ return; ++ + if (ctrl->ops->flags & NVME_F_FABRICS) { + /* + * The NVMe over Fabrics specification only supports metadata as +@@ -1743,10 +1744,21 @@ static int nvme_configure_metadata(struct nvme_ns *ns, struct nvme_id_ns *id) + * remap the separate metadata buffer from the block layer. + */ + if (WARN_ON_ONCE(!(id->flbas & NVME_NS_FLBAS_META_EXT))) +- return -EINVAL; +- if (ctrl->max_integrity_segments) +- ns->features |= +- (NVME_NS_METADATA_SUPPORTED | NVME_NS_EXT_LBAS); ++ return; ++ ++ ns->features |= NVME_NS_EXT_LBAS; ++ ++ /* ++ * The current fabrics transport drivers support namespace ++ * metadata formats only if nvme_ns_has_pi() returns true. ++ * Suppress support for all other formats so the namespace will ++ * have a 0 capacity and not be usable through the block stack. ++ * ++ * Note, this check will need to be modified if any drivers ++ * gain the ability to use other metadata formats. ++ */ ++ if (ctrl->max_integrity_segments && nvme_ns_has_pi(ns)) ++ ns->features |= NVME_NS_METADATA_SUPPORTED; + } else { + /* + * For PCIe controllers, we can't easily remap the separate +@@ -1759,8 +1771,6 @@ static int nvme_configure_metadata(struct nvme_ns *ns, struct nvme_id_ns *id) + else + ns->features |= NVME_NS_METADATA_SUPPORTED; + } +- +- return 0; + } + + static void nvme_set_queue_limits(struct nvme_ctrl *ctrl, +@@ -1898,16 +1908,16 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id) + ns->lba_shift = id->lbaf[lbaf].ds; + nvme_set_queue_limits(ns->ctrl, ns->queue); + +- ret = nvme_configure_metadata(ns, id); +- if (ret) +- goto out_unfreeze; ++ nvme_configure_metadata(ns, id); + nvme_set_chunk_sectors(ns, id); + nvme_update_disk_info(ns->disk, ns, id); + + if (ns->head->ids.csi == NVME_CSI_ZNS) { + ret = nvme_update_zone_info(ns, lbaf); +- if (ret) +- goto out_unfreeze; ++ if (ret) { ++ blk_mq_unfreeze_queue(ns->disk->queue); ++ goto out; ++ } + } + + set_disk_ro(ns->disk, (id->nsattr & NVME_NS_ATTR_RO) || +@@ -1918,7 +1928,7 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id) + if (blk_queue_is_zoned(ns->queue)) { + ret = nvme_revalidate_zones(ns); + if (ret && !nvme_first_scan(ns->disk)) +- return ret; ++ goto out; + } + + if (nvme_ns_head_multipath(ns->head)) { +@@ -1933,9 +1943,9 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id) + disk_update_readahead(ns->head->disk); + blk_mq_unfreeze_queue(ns->head->disk->queue); + } +- return 0; + +-out_unfreeze: ++ ret = 0; ++out: + /* + * If probing fails due an unsupported feature, hide the block device, + * but still allow other access. +@@ -1945,7 +1955,6 @@ out_unfreeze: + set_bit(NVME_NS_READY, &ns->flags); + ret = 0; + } +- blk_mq_unfreeze_queue(ns->disk->queue); + return ret; + } + +@@ -2102,6 +2111,7 @@ static int nvme_report_zones(struct gendisk *disk, sector_t sector, + static const struct block_device_operations nvme_bdev_ops = { + .owner = THIS_MODULE, + .ioctl = nvme_ioctl, ++ .compat_ioctl = blkdev_compat_ptr_ioctl, + .open = nvme_open, + .release = nvme_release, + .getgeo = nvme_getgeo, +diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c +index 064acad505d38..04fa276701d10 100644 +--- a/drivers/nvme/host/multipath.c ++++ b/drivers/nvme/host/multipath.c +@@ -388,6 +388,7 @@ const struct block_device_operations nvme_ns_head_ops = { + .open = nvme_ns_head_open, + .release = nvme_ns_head_release, + .ioctl = nvme_ns_head_ioctl, ++ .compat_ioctl = blkdev_compat_ptr_ioctl, + .getgeo = nvme_getgeo, + .report_zones = nvme_ns_head_report_zones, + .pr_ops = &nvme_pr_ops, +diff --git a/drivers/nvme/host/trace.h b/drivers/nvme/host/trace.h +index 35bac7a254227..aa8b0f86b2be1 100644 +--- a/drivers/nvme/host/trace.h ++++ b/drivers/nvme/host/trace.h +@@ -98,7 +98,7 @@ TRACE_EVENT(nvme_complete_rq, + TP_fast_assign( + __entry->ctrl_id = nvme_req(req)->ctrl->instance; + __entry->qid = nvme_req_qid(req); +- __entry->cid = req->tag; ++ __entry->cid = nvme_req(req)->cmd->common.command_id; + __entry->result = le64_to_cpu(nvme_req(req)->result.u64); + __entry->retries = nvme_req(req)->retries; + __entry->flags = nvme_req(req)->flags; +diff --git a/drivers/of/device.c b/drivers/of/device.c +index b0800c260f64a..45335fe523f7d 100644 +--- a/drivers/of/device.c ++++ b/drivers/of/device.c +@@ -81,8 +81,11 @@ of_dma_set_restricted_buffer(struct device *dev, struct device_node *np) + * restricted-dma-pool region is allowed. + */ + if (of_device_is_compatible(node, "restricted-dma-pool") && +- of_device_is_available(node)) ++ of_device_is_available(node)) { ++ of_node_put(node); + break; ++ } ++ of_node_put(node); + } + + /* +diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c +index 59a7a9ee58ef7..d245628b15dd4 100644 +--- a/drivers/of/fdt.c ++++ b/drivers/of/fdt.c +@@ -245,7 +245,7 @@ static int populate_node(const void *blob, + } + + *pnp = np; +- return true; ++ return 0; + } + + static void reverse_nodes(struct device_node *parent) +diff --git a/drivers/of/kexec.c b/drivers/of/kexec.c +index 72c790a3c910c..8f9dba11873cb 100644 +--- a/drivers/of/kexec.c ++++ b/drivers/of/kexec.c +@@ -125,6 +125,7 @@ int ima_get_kexec_buffer(void **addr, size_t *size) + { + int ret, len; + unsigned long tmp_addr; ++ unsigned long start_pfn, end_pfn; + size_t tmp_size; + const void *prop; + +@@ -139,6 +140,22 @@ int ima_get_kexec_buffer(void **addr, size_t *size) + if (ret) + return ret; + ++ /* Do some sanity on the returned size for the ima-kexec buffer */ ++ if (!tmp_size) ++ return -ENOENT; ++ ++ /* ++ * Calculate the PFNs for the buffer and ensure ++ * they are with in addressable memory. ++ */ ++ start_pfn = PHYS_PFN(tmp_addr); ++ end_pfn = PHYS_PFN(tmp_addr + tmp_size - 1); ++ if (!page_is_ram(start_pfn) || !page_is_ram(end_pfn)) { ++ pr_warn("IMA buffer at 0x%lx, size = 0x%zx beyond memory\n", ++ tmp_addr, tmp_size); ++ return -EINVAL; ++ } ++ + *addr = __va(tmp_addr); + *size = tmp_size; + +diff --git a/drivers/opp/core.c b/drivers/opp/core.c +index 04b4691a8aac7..b2da497dd378b 100644 +--- a/drivers/opp/core.c ++++ b/drivers/opp/core.c +@@ -2388,8 +2388,8 @@ struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, + } + + virt_dev = dev_pm_domain_attach_by_name(dev, *name); +- if (IS_ERR(virt_dev)) { +- ret = PTR_ERR(virt_dev); ++ if (IS_ERR_OR_NULL(virt_dev)) { ++ ret = PTR_ERR(virt_dev) ? : -ENODEV; + dev_err(dev, "Couldn't attach to pm_domain: %d\n", ret); + goto err; + } +diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c +index 732b516c7bf84..afc6e66ddc31c 100644 +--- a/drivers/parisc/lba_pci.c ++++ b/drivers/parisc/lba_pci.c +@@ -1476,9 +1476,13 @@ lba_driver_probe(struct parisc_device *dev) + u32 func_class; + void *tmp_obj; + char *version; +- void __iomem *addr = ioremap(dev->hpa.start, 4096); ++ void __iomem *addr; + int max; + ++ addr = ioremap(dev->hpa.start, 4096); ++ if (addr == NULL) ++ return -ENOMEM; ++ + /* Read HW Rev First */ + func_class = READ_REG32(addr + LBA_FCLASS); + +diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c +index 998b698f40858..2af4ed90e12b3 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-ep.c ++++ b/drivers/pci/controller/dwc/pcie-designware-ep.c +@@ -777,8 +777,9 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) + ep->msi_mem = pci_epc_mem_alloc_addr(epc, &ep->msi_mem_phys, + epc->mem->window.page_size); + if (!ep->msi_mem) { ++ ret = -ENOMEM; + dev_err(dev, "Failed to reserve memory for MSI/MSI-X\n"); +- return -ENOMEM; ++ goto err_exit_epc_mem; + } + + if (ep->ops->get_features) { +@@ -787,6 +788,19 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) + return 0; + } + +- return dw_pcie_ep_init_complete(ep); ++ ret = dw_pcie_ep_init_complete(ep); ++ if (ret) ++ goto err_free_epc_mem; ++ ++ return 0; ++ ++err_free_epc_mem: ++ pci_epc_mem_free_addr(epc, ep->msi_mem_phys, ep->msi_mem, ++ epc->mem->window.page_size); ++ ++err_exit_epc_mem: ++ pci_epc_mem_exit(epc); ++ ++ return ret; + } + EXPORT_SYMBOL_GPL(dw_pcie_ep_init); +diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c +index bc0807fe3fc35..7cd4593ad12fa 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-host.c ++++ b/drivers/pci/controller/dwc/pcie-designware-host.c +@@ -414,8 +414,14 @@ int dw_pcie_host_init(struct pcie_port *pp) + bridge->sysdata = pp; + + ret = pci_host_probe(bridge); +- if (!ret) +- return 0; ++ if (ret) ++ goto err_stop_link; ++ ++ return 0; ++ ++err_stop_link: ++ if (pci->ops && pci->ops->stop_link) ++ pci->ops->stop_link(pci); + + err_free_msi: + if (pp->has_msi_ctrl) +@@ -426,8 +432,14 @@ EXPORT_SYMBOL_GPL(dw_pcie_host_init); + + void dw_pcie_host_deinit(struct pcie_port *pp) + { ++ struct dw_pcie *pci = to_dw_pcie_from_pp(pp); ++ + pci_stop_root_bus(pp->bridge->bus); + pci_remove_root_bus(pp->bridge->bus); ++ ++ if (pci->ops && pci->ops->stop_link) ++ pci->ops->stop_link(pci); ++ + if (pp->has_msi_ctrl) + dw_pcie_free_msi(pp); + } +@@ -524,7 +536,6 @@ static struct pci_ops dw_pcie_ops = { + + void dw_pcie_setup_rc(struct pcie_port *pp) + { +- int i; + u32 val, ctrl, num_ctrls; + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + +@@ -576,19 +587,22 @@ void dw_pcie_setup_rc(struct pcie_port *pp) + PCI_COMMAND_MASTER | PCI_COMMAND_SERR; + dw_pcie_writel_dbi(pci, PCI_COMMAND, val); + +- /* Ensure all outbound windows are disabled so there are multiple matches */ +- for (i = 0; i < pci->num_ob_windows; i++) +- dw_pcie_disable_atu(pci, i, DW_PCIE_REGION_OUTBOUND); +- + /* + * If the platform provides its own child bus config accesses, it means + * the platform uses its own address translation component rather than + * ATU, so we should not program the ATU here. + */ + if (pp->bridge->child_ops == &dw_child_pcie_ops) { +- int atu_idx = 0; ++ int i, atu_idx = 0; + struct resource_entry *entry; + ++ /* ++ * Disable all outbound windows to make sure a transaction ++ * can't match multiple windows. ++ */ ++ for (i = 0; i < pci->num_ob_windows; i++) ++ dw_pcie_disable_atu(pci, i, DW_PCIE_REGION_OUTBOUND); ++ + /* Get last memory resource entry */ + resource_list_for_each_entry(entry, &pp->bridge->windows) { + if (resource_type(entry->res) != IORESOURCE_MEM) +diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c +index 3254f60d1713f..e408ebf5bd738 100644 +--- a/drivers/pci/controller/dwc/pcie-designware.c ++++ b/drivers/pci/controller/dwc/pcie-designware.c +@@ -287,8 +287,8 @@ static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, u8 func_no, + dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET, + upper_32_bits(pci_addr)); + val = type | PCIE_ATU_FUNC_NUM(func_no); +- val = upper_32_bits(size - 1) ? +- val | PCIE_ATU_INCREASE_REGION_SIZE : val; ++ if (upper_32_bits(limit_addr) > upper_32_bits(cpu_addr)) ++ val |= PCIE_ATU_INCREASE_REGION_SIZE; + if (pci->version == 0x490A) + val = dw_pcie_enable_ecrc(val); + dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1, val); +@@ -315,6 +315,7 @@ static void __dw_pcie_prog_outbound_atu(struct dw_pcie *pci, u8 func_no, + u64 pci_addr, u64 size) + { + u32 retries, val; ++ u64 limit_addr; + + if (pci->ops && pci->ops->cpu_addr_fixup) + cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr); +@@ -325,6 +326,8 @@ static void __dw_pcie_prog_outbound_atu(struct dw_pcie *pci, u8 func_no, + return; + } + ++ limit_addr = cpu_addr + size - 1; ++ + dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, + PCIE_ATU_REGION_OUTBOUND | index); + dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_BASE, +@@ -332,17 +335,18 @@ static void __dw_pcie_prog_outbound_atu(struct dw_pcie *pci, u8 func_no, + dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_BASE, + upper_32_bits(cpu_addr)); + dw_pcie_writel_dbi(pci, PCIE_ATU_LIMIT, +- lower_32_bits(cpu_addr + size - 1)); ++ lower_32_bits(limit_addr)); + if (pci->version >= 0x460A) + dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_LIMIT, +- upper_32_bits(cpu_addr + size - 1)); ++ upper_32_bits(limit_addr)); + dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_TARGET, + lower_32_bits(pci_addr)); + dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET, + upper_32_bits(pci_addr)); + val = type | PCIE_ATU_FUNC_NUM(func_no); +- val = ((upper_32_bits(size - 1)) && (pci->version >= 0x460A)) ? +- val | PCIE_ATU_INCREASE_REGION_SIZE : val; ++ if (upper_32_bits(limit_addr) > upper_32_bits(cpu_addr) && ++ pci->version >= 0x460A) ++ val |= PCIE_ATU_INCREASE_REGION_SIZE; + if (pci->version == 0x490A) + val = dw_pcie_enable_ecrc(val); + dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, val); +@@ -491,7 +495,7 @@ int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, u8 func_no, int index, + void dw_pcie_disable_atu(struct dw_pcie *pci, int index, + enum dw_pcie_region_type type) + { +- int region; ++ u32 region; + + switch (type) { + case DW_PCIE_REGION_INBOUND: +@@ -504,8 +508,18 @@ void dw_pcie_disable_atu(struct dw_pcie *pci, int index, + return; + } + +- dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, region | index); +- dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, ~(u32)PCIE_ATU_ENABLE); ++ if (pci->iatu_unroll_enabled) { ++ if (region == PCIE_ATU_REGION_INBOUND) { ++ dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2, ++ ~(u32)PCIE_ATU_ENABLE); ++ } else { ++ dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2, ++ ~(u32)PCIE_ATU_ENABLE); ++ } ++ } else { ++ dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, region | index); ++ dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, ~(u32)PCIE_ATU_ENABLE); ++ } + } + + int dw_pcie_wait_for_link(struct dw_pcie *pci) +@@ -725,6 +739,13 @@ void dw_pcie_setup(struct dw_pcie *pci) + val |= PORT_LINK_DLL_LINK_EN; + dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val); + ++ if (of_property_read_bool(np, "snps,enable-cdm-check")) { ++ val = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS); ++ val |= PCIE_PL_CHK_REG_CHK_REG_CONTINUOUS | ++ PCIE_PL_CHK_REG_CHK_REG_START; ++ dw_pcie_writel_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS, val); ++ } ++ + of_property_read_u32(np, "num-lanes", &pci->num_lanes); + if (!pci->num_lanes) { + dev_dbg(pci->dev, "Using h/w default number of lanes\n"); +@@ -771,11 +792,4 @@ void dw_pcie_setup(struct dw_pcie *pci) + break; + } + dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val); +- +- if (of_property_read_bool(np, "snps,enable-cdm-check")) { +- val = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS); +- val |= PCIE_PL_CHK_REG_CHK_REG_CONTINUOUS | +- PCIE_PL_CHK_REG_CHK_REG_START; +- dw_pcie_writel_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS, val); +- } + } +diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c +index b139a2e4af122..4c599699e3c88 100644 +--- a/drivers/pci/controller/dwc/pcie-qcom.c ++++ b/drivers/pci/controller/dwc/pcie-qcom.c +@@ -325,8 +325,6 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) + reset_control_assert(res->ext_reset); + reset_control_assert(res->phy_reset); + +- writel(1, pcie->parf + PCIE20_PARF_PHY_CTRL); +- + ret = regulator_bulk_enable(ARRAY_SIZE(res->supplies), res->supplies); + if (ret < 0) { + dev_err(dev, "cannot enable regulators\n"); +@@ -369,15 +367,15 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) + goto err_deassert_axi; + } + +- ret = clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks); +- if (ret) +- goto err_clks; +- + /* enable PCIe clocks and resets */ + val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); + val &= ~BIT(0); + writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); + ++ ret = clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks); ++ if (ret) ++ goto err_clks; ++ + if (of_device_is_compatible(node, "qcom,pcie-ipq8064") || + of_device_is_compatible(node, "qcom,pcie-ipq8064-v2")) { + writel(PCS_DEEMPH_TX_DEEMPH_GEN1(24) | +@@ -1026,9 +1024,7 @@ static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie) + struct qcom_pcie_resources_2_3_3 *res = &pcie->res.v2_3_3; + struct dw_pcie *pci = pcie->pci; + struct device *dev = pci->dev; +- u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); + int i, ret; +- u32 val; + + for (i = 0; i < ARRAY_SIZE(res->rst); i++) { + ret = reset_control_assert(res->rst[i]); +@@ -1085,6 +1081,33 @@ static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie) + goto err_clk_aux; + } + ++ return 0; ++ ++err_clk_aux: ++ clk_disable_unprepare(res->ahb_clk); ++err_clk_ahb: ++ clk_disable_unprepare(res->axi_s_clk); ++err_clk_axi_s: ++ clk_disable_unprepare(res->axi_m_clk); ++err_clk_axi_m: ++ clk_disable_unprepare(res->iface); ++err_clk_iface: ++ /* ++ * Not checking for failure, will anyway return ++ * the original failure in 'ret'. ++ */ ++ for (i = 0; i < ARRAY_SIZE(res->rst); i++) ++ reset_control_assert(res->rst[i]); ++ ++ return ret; ++} ++ ++static int qcom_pcie_post_init_2_3_3(struct qcom_pcie *pcie) ++{ ++ struct dw_pcie *pci = pcie->pci; ++ u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); ++ u32 val; ++ + writel(SLV_ADDR_SPACE_SZ, + pcie->parf + PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE); + +@@ -1112,24 +1135,6 @@ static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie) + PCI_EXP_DEVCTL2); + + return 0; +- +-err_clk_aux: +- clk_disable_unprepare(res->ahb_clk); +-err_clk_ahb: +- clk_disable_unprepare(res->axi_s_clk); +-err_clk_axi_s: +- clk_disable_unprepare(res->axi_m_clk); +-err_clk_axi_m: +- clk_disable_unprepare(res->iface); +-err_clk_iface: +- /* +- * Not checking for failure, will anyway return +- * the original failure in 'ret'. +- */ +- for (i = 0; i < ARRAY_SIZE(res->rst); i++) +- reset_control_assert(res->rst[i]); +- +- return ret; + } + + static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie) +@@ -1425,6 +1430,7 @@ static const struct qcom_pcie_ops ops_2_4_0 = { + static const struct qcom_pcie_ops ops_2_3_3 = { + .get_resources = qcom_pcie_get_resources_2_3_3, + .init = qcom_pcie_init_2_3_3, ++ .post_init = qcom_pcie_post_init_2_3_3, + .deinit = qcom_pcie_deinit_2_3_3, + .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable, + }; +diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c +index 9049769130819..bdd84765e6460 100644 +--- a/drivers/pci/controller/dwc/pcie-tegra194.c ++++ b/drivers/pci/controller/dwc/pcie-tegra194.c +@@ -352,15 +352,14 @@ static irqreturn_t tegra_pcie_rp_irq_handler(int irq, void *arg) + struct tegra_pcie_dw *pcie = arg; + struct dw_pcie *pci = &pcie->pci; + struct pcie_port *pp = &pci->pp; +- u32 val, tmp; ++ u32 val, status_l0, status_l1; + u16 val_w; + +- val = appl_readl(pcie, APPL_INTR_STATUS_L0); +- if (val & APPL_INTR_STATUS_L0_LINK_STATE_INT) { +- val = appl_readl(pcie, APPL_INTR_STATUS_L1_0_0); +- if (val & APPL_INTR_STATUS_L1_0_0_LINK_REQ_RST_NOT_CHGED) { +- appl_writel(pcie, val, APPL_INTR_STATUS_L1_0_0); +- ++ status_l0 = appl_readl(pcie, APPL_INTR_STATUS_L0); ++ if (status_l0 & APPL_INTR_STATUS_L0_LINK_STATE_INT) { ++ status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_0_0); ++ appl_writel(pcie, status_l1, APPL_INTR_STATUS_L1_0_0); ++ if (status_l1 & APPL_INTR_STATUS_L1_0_0_LINK_REQ_RST_NOT_CHGED) { + /* SBR & Surprise Link Down WAR */ + val = appl_readl(pcie, APPL_CAR_RESET_OVRD); + val &= ~APPL_CAR_RESET_OVRD_CYA_OVERRIDE_CORE_RST_N; +@@ -376,15 +375,15 @@ static irqreturn_t tegra_pcie_rp_irq_handler(int irq, void *arg) + } + } + +- if (val & APPL_INTR_STATUS_L0_INT_INT) { +- val = appl_readl(pcie, APPL_INTR_STATUS_L1_8_0); +- if (val & APPL_INTR_STATUS_L1_8_0_AUTO_BW_INT_STS) { ++ if (status_l0 & APPL_INTR_STATUS_L0_INT_INT) { ++ status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_8_0); ++ if (status_l1 & APPL_INTR_STATUS_L1_8_0_AUTO_BW_INT_STS) { + appl_writel(pcie, + APPL_INTR_STATUS_L1_8_0_AUTO_BW_INT_STS, + APPL_INTR_STATUS_L1_8_0); + apply_bad_link_workaround(pp); + } +- if (val & APPL_INTR_STATUS_L1_8_0_BW_MGT_INT_STS) { ++ if (status_l1 & APPL_INTR_STATUS_L1_8_0_BW_MGT_INT_STS) { + appl_writel(pcie, + APPL_INTR_STATUS_L1_8_0_BW_MGT_INT_STS, + APPL_INTR_STATUS_L1_8_0); +@@ -396,25 +395,24 @@ static irqreturn_t tegra_pcie_rp_irq_handler(int irq, void *arg) + } + } + +- val = appl_readl(pcie, APPL_INTR_STATUS_L0); +- if (val & APPL_INTR_STATUS_L0_CDM_REG_CHK_INT) { +- val = appl_readl(pcie, APPL_INTR_STATUS_L1_18); +- tmp = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS); +- if (val & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_CMPLT) { ++ if (status_l0 & APPL_INTR_STATUS_L0_CDM_REG_CHK_INT) { ++ status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_18); ++ val = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS); ++ if (status_l1 & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_CMPLT) { + dev_info(pci->dev, "CDM check complete\n"); +- tmp |= PCIE_PL_CHK_REG_CHK_REG_COMPLETE; ++ val |= PCIE_PL_CHK_REG_CHK_REG_COMPLETE; + } +- if (val & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_CMP_ERR) { ++ if (status_l1 & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_CMP_ERR) { + dev_err(pci->dev, "CDM comparison mismatch\n"); +- tmp |= PCIE_PL_CHK_REG_CHK_REG_COMPARISON_ERROR; ++ val |= PCIE_PL_CHK_REG_CHK_REG_COMPARISON_ERROR; + } +- if (val & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_LOGIC_ERR) { ++ if (status_l1 & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_LOGIC_ERR) { + dev_err(pci->dev, "CDM Logic error\n"); +- tmp |= PCIE_PL_CHK_REG_CHK_REG_LOGIC_ERROR; ++ val |= PCIE_PL_CHK_REG_CHK_REG_LOGIC_ERROR; + } +- dw_pcie_writel_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS, tmp); +- tmp = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_ERR_ADDR); +- dev_err(pci->dev, "CDM Error Address Offset = 0x%08X\n", tmp); ++ dw_pcie_writel_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS, val); ++ val = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_ERR_ADDR); ++ dev_err(pci->dev, "CDM Error Address Offset = 0x%08X\n", val); + } + + return IRQ_HANDLED; +@@ -980,7 +978,7 @@ retry_link: + offset = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_DLF); + val = dw_pcie_readl_dbi(pci, offset + PCI_DLF_CAP); + val &= ~PCI_DLF_EXCHANGE_ENABLE; +- dw_pcie_writel_dbi(pci, offset, val); ++ dw_pcie_writel_dbi(pci, offset + PCI_DLF_CAP, val); + + tegra_pcie_dw_host_init(pp); + dw_pcie_setup_rc(pp); +@@ -1951,6 +1949,7 @@ static int tegra_pcie_config_ep(struct tegra_pcie_dw *pcie, + if (ret) { + dev_err(dev, "Failed to initialize DWC Endpoint subsystem: %d\n", + ret); ++ pm_runtime_disable(dev); + return ret; + } + +diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c +index 21207df680ccf..36c8702439e95 100644 +--- a/drivers/pci/controller/pcie-mediatek-gen3.c ++++ b/drivers/pci/controller/pcie-mediatek-gen3.c +@@ -600,7 +600,8 @@ static int mtk_pcie_init_irq_domains(struct mtk_pcie_port *port) + &intx_domain_ops, port); + if (!port->intx_domain) { + dev_err(dev, "failed to create INTx IRQ domain\n"); +- return -ENODEV; ++ ret = -ENODEV; ++ goto out_put_node; + } + + /* Setup MSI */ +@@ -623,6 +624,7 @@ static int mtk_pcie_init_irq_domains(struct mtk_pcie_port *port) + goto err_msi_domain; + } + ++ of_node_put(intc_node); + return 0; + + err_msi_domain: +@@ -630,6 +632,8 @@ err_msi_domain: + err_msi_bottom_domain: + irq_domain_remove(port->intx_domain); + ++out_put_node: ++ of_node_put(intc_node); + return ret; + } + +diff --git a/drivers/pci/controller/pcie-microchip-host.c b/drivers/pci/controller/pcie-microchip-host.c +index fa209ad067bf8..6e8a6540b377b 100644 +--- a/drivers/pci/controller/pcie-microchip-host.c ++++ b/drivers/pci/controller/pcie-microchip-host.c +@@ -894,6 +894,7 @@ static int mc_pcie_init_irq_domains(struct mc_port *port) + &event_domain_ops, port); + if (!port->event_domain) { + dev_err(dev, "failed to get event domain\n"); ++ of_node_put(pcie_intc_node); + return -ENOMEM; + } + +@@ -903,6 +904,7 @@ static int mc_pcie_init_irq_domains(struct mc_port *port) + &intx_domain_ops, port); + if (!port->intx_domain) { + dev_err(dev, "failed to get an INTx IRQ domain\n"); ++ of_node_put(pcie_intc_node); + return -ENOMEM; + } + +diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c +index 5b833f00e9800..a5ed779b0a512 100644 +--- a/drivers/pci/endpoint/functions/pci-epf-test.c ++++ b/drivers/pci/endpoint/functions/pci-epf-test.c +@@ -627,7 +627,6 @@ static void pci_epf_test_unbind(struct pci_epf *epf) + + cancel_delayed_work(&epf_test->cmd_handler); + pci_epf_test_clean_dma_chan(epf_test); +- pci_epc_stop(epc); + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { + epf_bar = &epf->bar[bar]; + +diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c +index 50cdde3e9a8b2..316fd2f44df45 100644 +--- a/drivers/pci/p2pdma.c ++++ b/drivers/pci/p2pdma.c +@@ -219,7 +219,7 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size, + error = gen_pool_add_owner(p2pdma->pool, (unsigned long)addr, + pci_bus_address(pdev, bar) + offset, + range_len(&pgmap->range), dev_to_node(&pdev->dev), +- pgmap->ref); ++ &pgmap->ref); + if (error) + goto pages_free; + +diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c +index 80fe3e83c9f5a..ca9ac8c6a2021 100644 +--- a/drivers/pci/pcie/aer.c ++++ b/drivers/pci/pcie/aer.c +@@ -538,7 +538,7 @@ static const char *aer_agent_string[] = { + u64 *stats = pdev->aer_stats->stats_array; \ + size_t len = 0; \ + \ +- for (i = 0; i < ARRAY_SIZE(strings_array); i++) { \ ++ for (i = 0; i < ARRAY_SIZE(pdev->aer_stats->stats_array); i++) {\ + if (strings_array[i]) \ + len += sysfs_emit_at(buf, len, "%s %llu\n", \ + strings_array[i], \ +@@ -1347,6 +1347,11 @@ static int aer_probe(struct pcie_device *dev) + struct device *device = &dev->device; + struct pci_dev *port = dev->port; + ++ BUILD_BUG_ON(ARRAY_SIZE(aer_correctable_error_string) < ++ AER_MAX_TYPEOF_COR_ERRS); ++ BUILD_BUG_ON(ARRAY_SIZE(aer_uncorrectable_error_string) < ++ AER_MAX_TYPEOF_UNCOR_ERRS); ++ + /* Limit to Root Ports or Root Complex Event Collectors */ + if ((pci_pcie_type(port) != PCI_EXP_TYPE_RC_EC) && + (pci_pcie_type(port) != PCI_EXP_TYPE_ROOT_PORT)) +diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c +index 604feeb84ee40..1ac7fec47d6fb 100644 +--- a/drivers/pci/pcie/portdrv_core.c ++++ b/drivers/pci/pcie/portdrv_core.c +@@ -222,15 +222,8 @@ static int get_port_device_capability(struct pci_dev *dev) + + #ifdef CONFIG_PCIEAER + if (dev->aer_cap && pci_aer_available() && +- (pcie_ports_native || host->native_aer)) { ++ (pcie_ports_native || host->native_aer)) + services |= PCIE_PORT_SERVICE_AER; +- +- /* +- * Disable AER on this port in case it's been enabled by the +- * BIOS (the AER service driver will enable it when necessary). +- */ +- pci_disable_pcie_error_reporting(dev); +- } + #endif + + /* Root Ports and Root Complex Event Collectors may generate PMEs */ +diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c +index d44bcc29d99c8..cd5945e17fdf7 100644 +--- a/drivers/perf/arm_spe_pmu.c ++++ b/drivers/perf/arm_spe_pmu.c +@@ -39,6 +39,24 @@ + #include <asm/mmu.h> + #include <asm/sysreg.h> + ++/* ++ * Cache if the event is allowed to trace Context information. ++ * This allows us to perform the check, i.e, perfmon_capable(), ++ * in the context of the event owner, once, during the event_init(). ++ */ ++#define SPE_PMU_HW_FLAGS_CX BIT(0) ++ ++static void set_spe_event_has_cx(struct perf_event *event) ++{ ++ if (IS_ENABLED(CONFIG_PID_IN_CONTEXTIDR) && perfmon_capable()) ++ event->hw.flags |= SPE_PMU_HW_FLAGS_CX; ++} ++ ++static bool get_spe_event_has_cx(struct perf_event *event) ++{ ++ return !!(event->hw.flags & SPE_PMU_HW_FLAGS_CX); ++} ++ + #define ARM_SPE_BUF_PAD_BYTE 0 + + struct arm_spe_pmu_buf { +@@ -272,7 +290,7 @@ static u64 arm_spe_event_to_pmscr(struct perf_event *event) + if (!attr->exclude_kernel) + reg |= BIT(SYS_PMSCR_EL1_E1SPE_SHIFT); + +- if (IS_ENABLED(CONFIG_PID_IN_CONTEXTIDR) && perfmon_capable()) ++ if (get_spe_event_has_cx(event)) + reg |= BIT(SYS_PMSCR_EL1_CX_SHIFT); + + return reg; +@@ -709,10 +727,10 @@ static int arm_spe_pmu_event_init(struct perf_event *event) + !(spe_pmu->features & SPE_PMU_FEAT_FILT_LAT)) + return -EOPNOTSUPP; + ++ set_spe_event_has_cx(event); + reg = arm_spe_event_to_pmscr(event); + if (!perfmon_capable() && + (reg & (BIT(SYS_PMSCR_EL1_PA_SHIFT) | +- BIT(SYS_PMSCR_EL1_CX_SHIFT) | + BIT(SYS_PMSCR_EL1_PCT_SHIFT)))) + return -EACCES; + +diff --git a/drivers/phy/samsung/phy-exynosautov9-ufs.c b/drivers/phy/samsung/phy-exynosautov9-ufs.c +index 36398a15c2db7..d043dfdb598a2 100644 +--- a/drivers/phy/samsung/phy-exynosautov9-ufs.c ++++ b/drivers/phy/samsung/phy-exynosautov9-ufs.c +@@ -31,22 +31,22 @@ static const struct samsung_ufs_phy_cfg exynosautov9_pre_init_cfg[] = { + PHY_COMN_REG_CFG(0x023, 0xc0, PWR_MODE_ANY), + PHY_COMN_REG_CFG(0x023, 0x00, PWR_MODE_ANY), + +- PHY_TRSV_REG_CFG(0x042, 0x5d, PWR_MODE_ANY), +- PHY_TRSV_REG_CFG(0x043, 0x80, PWR_MODE_ANY), ++ PHY_TRSV_REG_CFG_AUTOV9(0x042, 0x5d, PWR_MODE_ANY), ++ PHY_TRSV_REG_CFG_AUTOV9(0x043, 0x80, PWR_MODE_ANY), + + END_UFS_PHY_CFG, + }; + + /* Calibration for HS mode series A/B */ + static const struct samsung_ufs_phy_cfg exynosautov9_pre_pwr_hs_cfg[] = { +- PHY_TRSV_REG_CFG(0x032, 0xbc, PWR_MODE_HS_ANY), +- PHY_TRSV_REG_CFG(0x03c, 0x7f, PWR_MODE_HS_ANY), +- PHY_TRSV_REG_CFG(0x048, 0xc0, PWR_MODE_HS_ANY), ++ PHY_TRSV_REG_CFG_AUTOV9(0x032, 0xbc, PWR_MODE_HS_ANY), ++ PHY_TRSV_REG_CFG_AUTOV9(0x03c, 0x7f, PWR_MODE_HS_ANY), ++ PHY_TRSV_REG_CFG_AUTOV9(0x048, 0xc0, PWR_MODE_HS_ANY), + +- PHY_TRSV_REG_CFG(0x04a, 0x00, PWR_MODE_HS_G3_SER_B), +- PHY_TRSV_REG_CFG(0x04b, 0x10, PWR_MODE_HS_G1_SER_B | +- PWR_MODE_HS_G3_SER_B), +- PHY_TRSV_REG_CFG(0x04d, 0x63, PWR_MODE_HS_G3_SER_B), ++ PHY_TRSV_REG_CFG_AUTOV9(0x04a, 0x00, PWR_MODE_HS_G3_SER_B), ++ PHY_TRSV_REG_CFG_AUTOV9(0x04b, 0x10, PWR_MODE_HS_G1_SER_B | ++ PWR_MODE_HS_G3_SER_B), ++ PHY_TRSV_REG_CFG_AUTOV9(0x04d, 0x63, PWR_MODE_HS_G3_SER_B), + + END_UFS_PHY_CFG, + }; +diff --git a/drivers/phy/st/phy-stm32-usbphyc.c b/drivers/phy/st/phy-stm32-usbphyc.c +index da05642d3bd4a..cd0747ab62677 100644 +--- a/drivers/phy/st/phy-stm32-usbphyc.c ++++ b/drivers/phy/st/phy-stm32-usbphyc.c +@@ -279,7 +279,9 @@ static int stm32_usbphyc_phy_init(struct phy *phy) + return 0; + + pll_disable: +- return stm32_usbphyc_pll_disable(usbphyc); ++ stm32_usbphyc_pll_disable(usbphyc); ++ ++ return ret; + } + + static int stm32_usbphyc_phy_exit(struct phy *phy) +diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c +index ff2a24b0c6114..4f0390b10cd3b 100644 +--- a/drivers/platform/chrome/cros_ec.c ++++ b/drivers/platform/chrome/cros_ec.c +@@ -135,16 +135,16 @@ static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event) + buf.msg.command = EC_CMD_HOST_SLEEP_EVENT; + + ret = cros_ec_cmd_xfer_status(ec_dev, &buf.msg); +- +- /* For now, report failure to transition to S0ix with a warning. */ ++ /* Report failure to transition to system wide suspend with a warning. */ + if (ret >= 0 && ec_dev->host_sleep_v1 && +- (sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME)) { ++ (sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME || ++ sleep_event == HOST_SLEEP_EVENT_S3_RESUME)) { + ec_dev->last_resume_result = + buf.u.resp1.resume_response.sleep_transitions; + + WARN_ONCE(buf.u.resp1.resume_response.sleep_transitions & + EC_HOST_RESUME_SLEEP_TIMEOUT, +- "EC detected sleep transition timeout. Total slp_s0 transitions: %d", ++ "EC detected sleep transition timeout. Total sleep transitions: %d", + buf.u.resp1.resume_response.sleep_transitions & + EC_HOST_RESUME_SLEEP_TRANSITIONS_MASK); + } +diff --git a/drivers/platform/olpc/olpc-ec.c b/drivers/platform/olpc/olpc-ec.c +index 4ff5c3a12991c..921520475ff68 100644 +--- a/drivers/platform/olpc/olpc-ec.c ++++ b/drivers/platform/olpc/olpc-ec.c +@@ -264,7 +264,7 @@ static ssize_t ec_dbgfs_cmd_write(struct file *file, const char __user *buf, + int i, m; + unsigned char ec_cmd[EC_MAX_CMD_ARGS]; + unsigned int ec_cmd_int[EC_MAX_CMD_ARGS]; +- char cmdbuf[64]; ++ char cmdbuf[64] = ""; + int ec_cmd_bytes; + + mutex_lock(&ec_dbgfs_lock); +diff --git a/drivers/pwm/pwm-lpc18xx-sct.c b/drivers/pwm/pwm-lpc18xx-sct.c +index 8cc8ae16553cf..43b5509dde513 100644 +--- a/drivers/pwm/pwm-lpc18xx-sct.c ++++ b/drivers/pwm/pwm-lpc18xx-sct.c +@@ -76,6 +76,8 @@ + #define LPC18XX_PWM_EVENT_PERIOD 0 + #define LPC18XX_PWM_EVENT_MAX 16 + ++#define LPC18XX_NUM_PWMS 16 ++ + /* SCT conflict resolution */ + enum lpc18xx_pwm_res_action { + LPC18XX_PWM_RES_NONE, +@@ -96,11 +98,12 @@ struct lpc18xx_pwm_chip { + unsigned long clk_rate; + unsigned int period_ns; + unsigned int min_period_ns; +- unsigned int max_period_ns; ++ u64 max_period_ns; + unsigned int period_event; + unsigned long event_map; + struct mutex res_lock; + struct mutex period_lock; ++ struct lpc18xx_pwm_data channeldata[LPC18XX_NUM_PWMS]; + }; + + static inline struct lpc18xx_pwm_chip * +@@ -142,40 +145,48 @@ static void lpc18xx_pwm_set_conflict_res(struct lpc18xx_pwm_chip *lpc18xx_pwm, + mutex_unlock(&lpc18xx_pwm->res_lock); + } + +-static void lpc18xx_pwm_config_period(struct pwm_chip *chip, int period_ns) ++static void lpc18xx_pwm_config_period(struct pwm_chip *chip, u64 period_ns) + { + struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); +- u64 val; ++ u32 val; + +- val = (u64)period_ns * lpc18xx_pwm->clk_rate; +- do_div(val, NSEC_PER_SEC); ++ /* ++ * With clk_rate < NSEC_PER_SEC this cannot overflow. ++ * With period_ns < max_period_ns this also fits into an u32. ++ * As period_ns >= min_period_ns = DIV_ROUND_UP(NSEC_PER_SEC, lpc18xx_pwm->clk_rate); ++ * we have val >= 1. ++ */ ++ val = mul_u64_u64_div_u64(period_ns, lpc18xx_pwm->clk_rate, NSEC_PER_SEC); + + lpc18xx_pwm_writel(lpc18xx_pwm, + LPC18XX_PWM_MATCH(lpc18xx_pwm->period_event), +- (u32)val - 1); ++ val - 1); + + lpc18xx_pwm_writel(lpc18xx_pwm, + LPC18XX_PWM_MATCHREL(lpc18xx_pwm->period_event), +- (u32)val - 1); ++ val - 1); + } + + static void lpc18xx_pwm_config_duty(struct pwm_chip *chip, +- struct pwm_device *pwm, int duty_ns) ++ struct pwm_device *pwm, u64 duty_ns) + { + struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); +- struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm); +- u64 val; ++ struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm]; ++ u32 val; + +- val = (u64)duty_ns * lpc18xx_pwm->clk_rate; +- do_div(val, NSEC_PER_SEC); ++ /* ++ * With clk_rate < NSEC_PER_SEC this cannot overflow. ++ * With duty_ns <= period_ns < max_period_ns this also fits into an u32. ++ */ ++ val = mul_u64_u64_div_u64(duty_ns, lpc18xx_pwm->clk_rate, NSEC_PER_SEC); + + lpc18xx_pwm_writel(lpc18xx_pwm, + LPC18XX_PWM_MATCH(lpc18xx_data->duty_event), +- (u32)val); ++ val); + + lpc18xx_pwm_writel(lpc18xx_pwm, + LPC18XX_PWM_MATCHREL(lpc18xx_data->duty_event), +- (u32)val); ++ val); + } + + static int lpc18xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, +@@ -233,7 +244,7 @@ static int lpc18xx_pwm_set_polarity(struct pwm_chip *chip, + static int lpc18xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) + { + struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); +- struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm); ++ struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm]; + enum lpc18xx_pwm_res_action res_action; + unsigned int set_event, clear_event; + +@@ -268,7 +279,7 @@ static int lpc18xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) + static void lpc18xx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) + { + struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); +- struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm); ++ struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm]; + + lpc18xx_pwm_writel(lpc18xx_pwm, + LPC18XX_PWM_EVCTRL(lpc18xx_data->duty_event), 0); +@@ -279,7 +290,7 @@ static void lpc18xx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) + static int lpc18xx_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) + { + struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); +- struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm); ++ struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm]; + unsigned long event; + + event = find_first_zero_bit(&lpc18xx_pwm->event_map, +@@ -300,7 +311,7 @@ static int lpc18xx_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) + static void lpc18xx_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) + { + struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip); +- struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm); ++ struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm]; + + clear_bit(lpc18xx_data->duty_event, &lpc18xx_pwm->event_map); + } +@@ -324,8 +335,7 @@ MODULE_DEVICE_TABLE(of, lpc18xx_pwm_of_match); + static int lpc18xx_pwm_probe(struct platform_device *pdev) + { + struct lpc18xx_pwm_chip *lpc18xx_pwm; +- struct pwm_device *pwm; +- int ret, i; ++ int ret; + u64 val; + + lpc18xx_pwm = devm_kzalloc(&pdev->dev, sizeof(*lpc18xx_pwm), +@@ -358,19 +368,34 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev) + goto disable_pwmclk; + } + ++ /* ++ * If clkrate is too fast, the calculations in .apply() might overflow. ++ */ ++ if (lpc18xx_pwm->clk_rate > NSEC_PER_SEC) { ++ ret = dev_err_probe(&pdev->dev, -EINVAL, "pwm clock to fast\n"); ++ goto disable_pwmclk; ++ } ++ ++ /* ++ * If clkrate is too fast, the calculations in .apply() might overflow. ++ */ ++ if (lpc18xx_pwm->clk_rate > NSEC_PER_SEC) { ++ ret = dev_err_probe(&pdev->dev, -EINVAL, "pwm clock to fast\n"); ++ goto disable_pwmclk; ++ } ++ + mutex_init(&lpc18xx_pwm->res_lock); + mutex_init(&lpc18xx_pwm->period_lock); + +- val = (u64)NSEC_PER_SEC * LPC18XX_PWM_TIMER_MAX; +- do_div(val, lpc18xx_pwm->clk_rate); +- lpc18xx_pwm->max_period_ns = val; ++ lpc18xx_pwm->max_period_ns = ++ mul_u64_u64_div_u64(NSEC_PER_SEC, LPC18XX_PWM_TIMER_MAX, lpc18xx_pwm->clk_rate); + + lpc18xx_pwm->min_period_ns = DIV_ROUND_UP(NSEC_PER_SEC, + lpc18xx_pwm->clk_rate); + + lpc18xx_pwm->chip.dev = &pdev->dev; + lpc18xx_pwm->chip.ops = &lpc18xx_pwm_ops; +- lpc18xx_pwm->chip.npwm = 16; ++ lpc18xx_pwm->chip.npwm = LPC18XX_NUM_PWMS; + + /* SCT counter must be in unify (32 bit) mode */ + lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CONFIG, +@@ -395,21 +420,6 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev) + lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_LIMIT, + BIT(lpc18xx_pwm->period_event)); + +- for (i = 0; i < lpc18xx_pwm->chip.npwm; i++) { +- struct lpc18xx_pwm_data *data; +- +- pwm = &lpc18xx_pwm->chip.pwms[i]; +- +- data = devm_kzalloc(lpc18xx_pwm->dev, sizeof(*data), +- GFP_KERNEL); +- if (!data) { +- ret = -ENOMEM; +- goto disable_pwmclk; +- } +- +- pwm_set_chip_data(pwm, data); +- } +- + val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_CTRL); + val &= ~LPC18XX_PWM_BIDIR; + val &= ~LPC18XX_PWM_CTRL_HALT; +diff --git a/drivers/pwm/pwm-sifive.c b/drivers/pwm/pwm-sifive.c +index 253c4a17d2553..58347fcd48125 100644 +--- a/drivers/pwm/pwm-sifive.c ++++ b/drivers/pwm/pwm-sifive.c +@@ -23,7 +23,7 @@ + #define PWM_SIFIVE_PWMCFG 0x0 + #define PWM_SIFIVE_PWMCOUNT 0x8 + #define PWM_SIFIVE_PWMS 0x10 +-#define PWM_SIFIVE_PWMCMP0 0x20 ++#define PWM_SIFIVE_PWMCMP(i) (0x20 + 4 * (i)) + + /* PWMCFG fields */ + #define PWM_SIFIVE_PWMCFG_SCALE GENMASK(3, 0) +@@ -36,8 +36,6 @@ + #define PWM_SIFIVE_PWMCFG_GANG BIT(24) + #define PWM_SIFIVE_PWMCFG_IP BIT(28) + +-/* PWM_SIFIVE_SIZE_PWMCMP is used to calculate offset for pwmcmpX registers */ +-#define PWM_SIFIVE_SIZE_PWMCMP 4 + #define PWM_SIFIVE_CMPWIDTH 16 + #define PWM_SIFIVE_DEFAULT_PERIOD 10000000 + +@@ -112,8 +110,7 @@ static void pwm_sifive_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_sifive_ddata *ddata = pwm_sifive_chip_to_ddata(chip); + u32 duty, val; + +- duty = readl(ddata->regs + PWM_SIFIVE_PWMCMP0 + +- pwm->hwpwm * PWM_SIFIVE_SIZE_PWMCMP); ++ duty = readl(ddata->regs + PWM_SIFIVE_PWMCMP(pwm->hwpwm)); + + state->enabled = duty > 0; + +@@ -194,8 +191,7 @@ static int pwm_sifive_apply(struct pwm_chip *chip, struct pwm_device *pwm, + pwm_sifive_update_clock(ddata, clk_get_rate(ddata->clk)); + } + +- writel(frac, ddata->regs + PWM_SIFIVE_PWMCMP0 + +- pwm->hwpwm * PWM_SIFIVE_SIZE_PWMCMP); ++ writel(frac, ddata->regs + PWM_SIFIVE_PWMCMP(pwm->hwpwm)); + + if (state->enabled != enabled) + pwm_sifive_enable(chip, state->enabled); +@@ -233,6 +229,8 @@ static int pwm_sifive_probe(struct platform_device *pdev) + struct pwm_sifive_ddata *ddata; + struct pwm_chip *chip; + int ret; ++ u32 val; ++ unsigned int enabled_pwms = 0, enabled_clks = 1; + + ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); + if (!ddata) +@@ -259,6 +257,33 @@ static int pwm_sifive_probe(struct platform_device *pdev) + return ret; + } + ++ val = readl(ddata->regs + PWM_SIFIVE_PWMCFG); ++ if (val & PWM_SIFIVE_PWMCFG_EN_ALWAYS) { ++ unsigned int i; ++ ++ for (i = 0; i < chip->npwm; ++i) { ++ val = readl(ddata->regs + PWM_SIFIVE_PWMCMP(i)); ++ if (val > 0) ++ ++enabled_pwms; ++ } ++ } ++ ++ /* The clk should be on once for each running PWM. */ ++ if (enabled_pwms) { ++ while (enabled_clks < enabled_pwms) { ++ /* This is not expected to fail as the clk is already on */ ++ ret = clk_enable(ddata->clk); ++ if (unlikely(ret)) { ++ dev_err_probe(dev, ret, "Failed to enable clk\n"); ++ goto disable_clk; ++ } ++ ++enabled_clks; ++ } ++ } else { ++ clk_disable(ddata->clk); ++ enabled_clks = 0; ++ } ++ + /* Watch for changes to underlying clock frequency */ + ddata->notifier.notifier_call = pwm_sifive_clock_notifier; + ret = clk_notifier_register(ddata->clk, &ddata->notifier); +@@ -281,7 +306,11 @@ static int pwm_sifive_probe(struct platform_device *pdev) + unregister_clk: + clk_notifier_unregister(ddata->clk, &ddata->notifier); + disable_clk: +- clk_disable_unprepare(ddata->clk); ++ while (enabled_clks) { ++ clk_disable(ddata->clk); ++ --enabled_clks; ++ } ++ clk_unprepare(ddata->clk); + + return ret; + } +@@ -289,23 +318,19 @@ disable_clk: + static int pwm_sifive_remove(struct platform_device *dev) + { + struct pwm_sifive_ddata *ddata = platform_get_drvdata(dev); +- bool is_enabled = false; + struct pwm_device *pwm; + int ch; + ++ pwmchip_remove(&ddata->chip); ++ clk_notifier_unregister(ddata->clk, &ddata->notifier); ++ + for (ch = 0; ch < ddata->chip.npwm; ch++) { + pwm = &ddata->chip.pwms[ch]; +- if (pwm->state.enabled) { +- is_enabled = true; +- break; +- } ++ if (pwm->state.enabled) ++ clk_disable(ddata->clk); + } +- if (is_enabled) +- clk_disable(ddata->clk); + +- clk_disable_unprepare(ddata->clk); +- pwmchip_remove(&ddata->chip); +- clk_notifier_unregister(ddata->clk, &ddata->notifier); ++ clk_unprepare(ddata->clk); + + return 0; + } +diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c +index f54d4f176882a..e12b681c72e5e 100644 +--- a/drivers/regulator/of_regulator.c ++++ b/drivers/regulator/of_regulator.c +@@ -264,8 +264,12 @@ static int of_get_regulation_constraints(struct device *dev, + } + + suspend_np = of_get_child_by_name(np, regulator_states[i]); +- if (!suspend_np || !suspend_state) ++ if (!suspend_np) + continue; ++ if (!suspend_state) { ++ of_node_put(suspend_np); ++ continue; ++ } + + if (!of_property_read_u32(suspend_np, "regulator-mode", + &pval)) { +diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c +index eb974b9c0b194..2fe13c765effb 100644 +--- a/drivers/regulator/qcom_smd-regulator.c ++++ b/drivers/regulator/qcom_smd-regulator.c +@@ -357,10 +357,10 @@ static const struct regulator_desc pm8941_switch = { + + static const struct regulator_desc pm8916_pldo = { + .linear_ranges = (struct linear_range[]) { +- REGULATOR_LINEAR_RANGE(750000, 0, 208, 12500), ++ REGULATOR_LINEAR_RANGE(1750000, 0, 127, 12500), + }, + .n_linear_ranges = 1, +- .n_voltages = 209, ++ .n_voltages = 128, + .ops = &rpm_smps_ldo_ops, + }; + +diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c +index 59eae605ad59f..e8a170ad43c1d 100644 +--- a/drivers/remoteproc/imx_rproc.c ++++ b/drivers/remoteproc/imx_rproc.c +@@ -586,16 +586,17 @@ static int imx_rproc_addr_init(struct imx_rproc *priv, + + node = of_parse_phandle(np, "memory-region", a); + /* Not map vdevbuffer, vdevring region */ +- if (!strncmp(node->name, "vdev", strlen("vdev"))) ++ if (!strncmp(node->name, "vdev", strlen("vdev"))) { ++ of_node_put(node); + continue; ++ } + err = of_address_to_resource(node, 0, &res); ++ of_node_put(node); + if (err) { + dev_err(dev, "unable to resolve memory region\n"); + return err; + } + +- of_node_put(node); +- + if (b >= IMX_RPROC_MEM_MAX) + break; + +diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c +index 699eaac5b760e..78d90d856e405 100644 +--- a/drivers/remoteproc/qcom_q6v5_pas.c ++++ b/drivers/remoteproc/qcom_q6v5_pas.c +@@ -87,6 +87,9 @@ static void adsp_minidump(struct rproc *rproc) + { + struct qcom_adsp *adsp = rproc->priv; + ++ if (rproc->dump_conf == RPROC_COREDUMP_DISABLED) ++ return; ++ + qcom_minidump(rproc, adsp->minidump_id); + } + +diff --git a/drivers/remoteproc/qcom_sysmon.c b/drivers/remoteproc/qcom_sysmon.c +index 9fca814928635..a9f04dd83ab68 100644 +--- a/drivers/remoteproc/qcom_sysmon.c ++++ b/drivers/remoteproc/qcom_sysmon.c +@@ -41,6 +41,7 @@ struct qcom_sysmon { + struct completion comp; + struct completion ind_comp; + struct completion shutdown_comp; ++ struct completion ssctl_comp; + struct mutex lock; + + bool ssr_ack; +@@ -445,6 +446,8 @@ static int ssctl_new_server(struct qmi_handle *qmi, struct qmi_service *svc) + + svc->priv = sysmon; + ++ complete(&sysmon->ssctl_comp); ++ + return 0; + } + +@@ -501,6 +504,7 @@ static int sysmon_start(struct rproc_subdev *subdev) + .ssr_event = SSCTL_SSR_EVENT_AFTER_POWERUP + }; + ++ reinit_completion(&sysmon->ssctl_comp); + mutex_lock(&sysmon->state_lock); + sysmon->state = SSCTL_SSR_EVENT_AFTER_POWERUP; + blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event); +@@ -545,6 +549,11 @@ static void sysmon_stop(struct rproc_subdev *subdev, bool crashed) + if (crashed) + return; + ++ if (sysmon->ssctl_instance) { ++ if (!wait_for_completion_timeout(&sysmon->ssctl_comp, HZ / 2)) ++ dev_err(sysmon->dev, "timeout waiting for ssctl service\n"); ++ } ++ + if (sysmon->ssctl_version) + sysmon->shutdown_acked = ssctl_request_shutdown(sysmon); + else if (sysmon->ept) +@@ -631,6 +640,7 @@ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc, + init_completion(&sysmon->comp); + init_completion(&sysmon->ind_comp); + init_completion(&sysmon->shutdown_comp); ++ init_completion(&sysmon->ssctl_comp); + mutex_init(&sysmon->lock); + mutex_init(&sysmon->state_lock); + +diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c +index b17742eac9ffd..97a0c0dc4c77a 100644 +--- a/drivers/remoteproc/qcom_wcnss.c ++++ b/drivers/remoteproc/qcom_wcnss.c +@@ -468,6 +468,7 @@ static int wcnss_request_irq(struct qcom_wcnss *wcnss, + irq_handler_t thread_fn) + { + int ret; ++ int irq_number; + + ret = platform_get_irq_byname(pdev, name); + if (ret < 0 && optional) { +@@ -478,14 +479,19 @@ static int wcnss_request_irq(struct qcom_wcnss *wcnss, + return ret; + } + ++ irq_number = ret; ++ + ret = devm_request_threaded_irq(&pdev->dev, ret, + NULL, thread_fn, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "wcnss", wcnss); +- if (ret) ++ if (ret) { + dev_err(&pdev->dev, "request %s IRQ failed\n", name); ++ return ret; ++ } + +- return ret; ++ /* Return the IRQ number if the IRQ was successfully acquired */ ++ return irq_number; + } + + static int wcnss_alloc_memory_region(struct qcom_wcnss *wcnss) +diff --git a/drivers/remoteproc/ti_k3_r5_remoteproc.c b/drivers/remoteproc/ti_k3_r5_remoteproc.c +index 71615210df3e0..54266ea69c84d 100644 +--- a/drivers/remoteproc/ti_k3_r5_remoteproc.c ++++ b/drivers/remoteproc/ti_k3_r5_remoteproc.c +@@ -1430,6 +1430,7 @@ static int k3_r5_cluster_of_init(struct platform_device *pdev) + if (!cpdev) { + ret = -ENODEV; + dev_err(dev, "could not get R5 core platform device\n"); ++ of_node_put(child); + goto fail; + } + +@@ -1438,6 +1439,7 @@ static int k3_r5_cluster_of_init(struct platform_device *pdev) + dev_err(dev, "k3_r5_core_of_init failed, ret = %d\n", + ret); + put_device(&cpdev->dev); ++ of_node_put(child); + goto fail; + } + +diff --git a/drivers/rpmsg/mtk_rpmsg.c b/drivers/rpmsg/mtk_rpmsg.c +index 96a17ec291401..2d8cb596ad691 100644 +--- a/drivers/rpmsg/mtk_rpmsg.c ++++ b/drivers/rpmsg/mtk_rpmsg.c +@@ -234,7 +234,9 @@ static void mtk_register_device_work_function(struct work_struct *register_work) + if (info->registered) + continue; + ++ mutex_unlock(&subdev->channels_lock); + ret = mtk_rpmsg_register_device(subdev, &info->info); ++ mutex_lock(&subdev->channels_lock); + if (ret) { + dev_err(&pdev->dev, "Can't create rpmsg_device\n"); + continue; +diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c +index 370688e8646bf..c1c07ff39a796 100644 +--- a/drivers/rpmsg/qcom_smd.c ++++ b/drivers/rpmsg/qcom_smd.c +@@ -1380,6 +1380,7 @@ static int qcom_smd_parse_edge(struct device *dev, + } + + edge->ipc_regmap = syscon_node_to_regmap(syscon_np); ++ of_node_put(syscon_np); + if (IS_ERR(edge->ipc_regmap)) { + ret = PTR_ERR(edge->ipc_regmap); + goto put_node; +diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c +index 49dd5a2009982..88c985f9e73ab 100644 +--- a/drivers/rpmsg/rpmsg_char.c ++++ b/drivers/rpmsg/rpmsg_char.c +@@ -127,8 +127,11 @@ static int rpmsg_eptdev_open(struct inode *inode, struct file *filp) + struct rpmsg_device *rpdev = eptdev->rpdev; + struct device *dev = &eptdev->dev; + +- if (eptdev->ept) ++ mutex_lock(&eptdev->ept_lock); ++ if (eptdev->ept) { ++ mutex_unlock(&eptdev->ept_lock); + return -EBUSY; ++ } + + get_device(dev); + +@@ -136,11 +139,13 @@ static int rpmsg_eptdev_open(struct inode *inode, struct file *filp) + if (!ept) { + dev_err(dev, "failed to open %s\n", eptdev->chinfo.name); + put_device(dev); ++ mutex_unlock(&eptdev->ept_lock); + return -EINVAL; + } + + eptdev->ept = ept; + filp->private_data = eptdev; ++ mutex_unlock(&eptdev->ept_lock); + + return 0; + } +diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c +index d38aaf08108c2..dc9221393080a 100644 +--- a/drivers/rtc/rtc-rx8025.c ++++ b/drivers/rtc/rtc-rx8025.c +@@ -55,6 +55,8 @@ + #define RX8025_BIT_CTRL2_XST BIT(5) + #define RX8025_BIT_CTRL2_VDET BIT(6) + ++#define RX8035_BIT_HOUR_1224 BIT(7) ++ + /* Clock precision adjustment */ + #define RX8025_ADJ_RESOLUTION 3050 /* in ppb */ + #define RX8025_ADJ_DATA_MAX 62 +@@ -78,6 +80,7 @@ struct rx8025_data { + struct rtc_device *rtc; + enum rx_model model; + u8 ctrl1; ++ int is_24; + }; + + static s32 rx8025_read_reg(const struct i2c_client *client, u8 number) +@@ -226,7 +229,7 @@ static int rx8025_get_time(struct device *dev, struct rtc_time *dt) + + dt->tm_sec = bcd2bin(date[RX8025_REG_SEC] & 0x7f); + dt->tm_min = bcd2bin(date[RX8025_REG_MIN] & 0x7f); +- if (rx8025->ctrl1 & RX8025_BIT_CTRL1_1224) ++ if (rx8025->is_24) + dt->tm_hour = bcd2bin(date[RX8025_REG_HOUR] & 0x3f); + else + dt->tm_hour = bcd2bin(date[RX8025_REG_HOUR] & 0x1f) % 12 +@@ -257,7 +260,7 @@ static int rx8025_set_time(struct device *dev, struct rtc_time *dt) + */ + date[RX8025_REG_SEC] = bin2bcd(dt->tm_sec); + date[RX8025_REG_MIN] = bin2bcd(dt->tm_min); +- if (rx8025->ctrl1 & RX8025_BIT_CTRL1_1224) ++ if (rx8025->is_24) + date[RX8025_REG_HOUR] = bin2bcd(dt->tm_hour); + else + date[RX8025_REG_HOUR] = (dt->tm_hour >= 12 ? 0x20 : 0) +@@ -282,6 +285,7 @@ static int rx8025_init_client(struct i2c_client *client) + struct rx8025_data *rx8025 = i2c_get_clientdata(client); + u8 ctrl[2], ctrl2; + int need_clear = 0; ++ int hour_reg; + int err; + + err = rx8025_read_regs(client, RX8025_REG_CTRL1, 2, ctrl); +@@ -306,6 +310,16 @@ static int rx8025_init_client(struct i2c_client *client) + + err = rx8025_write_reg(client, RX8025_REG_CTRL2, ctrl2); + } ++ ++ if (rx8025->model == model_rx_8035) { ++ /* In RX-8035, 12/24 flag is in the hour register */ ++ hour_reg = rx8025_read_reg(client, RX8025_REG_HOUR); ++ if (hour_reg < 0) ++ return hour_reg; ++ rx8025->is_24 = (hour_reg & RX8035_BIT_HOUR_1224); ++ } else { ++ rx8025->is_24 = (ctrl[1] & RX8025_BIT_CTRL1_1224); ++ } + out: + return err; + } +@@ -335,7 +349,7 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t) + /* Hardware alarms precision is 1 minute! */ + t->time.tm_sec = 0; + t->time.tm_min = bcd2bin(ald[0] & 0x7f); +- if (rx8025->ctrl1 & RX8025_BIT_CTRL1_1224) ++ if (rx8025->is_24) + t->time.tm_hour = bcd2bin(ald[1] & 0x3f); + else + t->time.tm_hour = bcd2bin(ald[1] & 0x1f) % 12 +@@ -370,7 +384,7 @@ static int rx8025_set_alarm(struct device *dev, struct rtc_wkalrm *t) + } + + ald[0] = bin2bcd(t->time.tm_min); +- if (rx8025->ctrl1 & RX8025_BIT_CTRL1_1224) ++ if (rx8025->is_24) + ald[1] = bin2bcd(t->time.tm_hour); + else + ald[1] = (t->time.tm_hour >= 12 ? 0x20 : 0) +diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c +index 3ba2d934a3e89..92b32ce645b95 100644 +--- a/drivers/s390/char/zcore.c ++++ b/drivers/s390/char/zcore.c +@@ -50,6 +50,7 @@ static struct dentry *zcore_reipl_file; + static struct dentry *zcore_hsa_file; + static struct ipl_parameter_block *zcore_ipl_block; + ++static DEFINE_MUTEX(hsa_buf_mutex); + static char hsa_buf[PAGE_SIZE] __aligned(PAGE_SIZE); + + /* +@@ -66,19 +67,24 @@ int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count) + if (!hsa_available) + return -ENODATA; + ++ mutex_lock(&hsa_buf_mutex); + while (count) { + if (sclp_sdias_copy(hsa_buf, src / PAGE_SIZE + 2, 1)) { + TRACE("sclp_sdias_copy() failed\n"); ++ mutex_unlock(&hsa_buf_mutex); + return -EIO; + } + offset = src % PAGE_SIZE; + bytes = min(PAGE_SIZE - offset, count); +- if (copy_to_user(dest, hsa_buf + offset, bytes)) ++ if (copy_to_user(dest, hsa_buf + offset, bytes)) { ++ mutex_unlock(&hsa_buf_mutex); + return -EFAULT; ++ } + src += bytes; + dest += bytes; + count -= bytes; + } ++ mutex_unlock(&hsa_buf_mutex); + return 0; + } + +@@ -96,9 +102,11 @@ int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count) + if (!hsa_available) + return -ENODATA; + ++ mutex_lock(&hsa_buf_mutex); + while (count) { + if (sclp_sdias_copy(hsa_buf, src / PAGE_SIZE + 2, 1)) { + TRACE("sclp_sdias_copy() failed\n"); ++ mutex_unlock(&hsa_buf_mutex); + return -EIO; + } + offset = src % PAGE_SIZE; +@@ -108,6 +116,7 @@ int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count) + dest += bytes; + count -= bytes; + } ++ mutex_unlock(&hsa_buf_mutex); + return 0; + } + +@@ -229,8 +238,7 @@ static int __init zcore_reipl_init(void) + rc = memcpy_hsa_kernel(zcore_ipl_block, ipib_info.ipib, + PAGE_SIZE); + else +- rc = memcpy_real(zcore_ipl_block, (void *) ipib_info.ipib, +- PAGE_SIZE); ++ rc = memcpy_real(zcore_ipl_block, ipib_info.ipib, PAGE_SIZE); + if (rc || (__force u32)csum_partial(zcore_ipl_block, zcore_ipl_block->hdr.len, 0) != + ipib_info.checksum) { + TRACE("Checksum does not match\n"); +diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c +index 76099bcb765b4..b9091e22ca572 100644 +--- a/drivers/s390/cio/vfio_ccw_drv.c ++++ b/drivers/s390/cio/vfio_ccw_drv.c +@@ -287,19 +287,11 @@ static int vfio_ccw_sch_event(struct subchannel *sch, int process) + if (work_pending(&sch->todo_work)) + goto out_unlock; + +- if (cio_update_schib(sch)) { +- vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER); +- rc = 0; +- goto out_unlock; +- } +- +- private = dev_get_drvdata(&sch->dev); +- if (private->state == VFIO_CCW_STATE_NOT_OPER) { +- private->state = private->mdev ? VFIO_CCW_STATE_IDLE : +- VFIO_CCW_STATE_STANDBY; +- } + rc = 0; + ++ if (cio_update_schib(sch)) ++ vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER); ++ + out_unlock: + spin_unlock_irqrestore(sch->lock, flags); + +diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c +index 511bf8e0a436c..b61acbb09be3b 100644 +--- a/drivers/s390/scsi/zfcp_fc.c ++++ b/drivers/s390/scsi/zfcp_fc.c +@@ -145,27 +145,33 @@ void zfcp_fc_enqueue_event(struct zfcp_adapter *adapter, + + static int zfcp_fc_wka_port_get(struct zfcp_fc_wka_port *wka_port) + { ++ int ret = -EIO; ++ + if (mutex_lock_interruptible(&wka_port->mutex)) + return -ERESTARTSYS; + + if (wka_port->status == ZFCP_FC_WKA_PORT_OFFLINE || + wka_port->status == ZFCP_FC_WKA_PORT_CLOSING) { + wka_port->status = ZFCP_FC_WKA_PORT_OPENING; +- if (zfcp_fsf_open_wka_port(wka_port)) ++ if (zfcp_fsf_open_wka_port(wka_port)) { ++ /* could not even send request, nothing to wait for */ + wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE; ++ goto out; ++ } + } + +- mutex_unlock(&wka_port->mutex); +- +- wait_event(wka_port->completion_wq, ++ wait_event(wka_port->opened, + wka_port->status == ZFCP_FC_WKA_PORT_ONLINE || + wka_port->status == ZFCP_FC_WKA_PORT_OFFLINE); + + if (wka_port->status == ZFCP_FC_WKA_PORT_ONLINE) { + atomic_inc(&wka_port->refcount); +- return 0; ++ ret = 0; ++ goto out; + } +- return -EIO; ++out: ++ mutex_unlock(&wka_port->mutex); ++ return ret; + } + + static void zfcp_fc_wka_port_offline(struct work_struct *work) +@@ -181,9 +187,12 @@ static void zfcp_fc_wka_port_offline(struct work_struct *work) + + wka_port->status = ZFCP_FC_WKA_PORT_CLOSING; + if (zfcp_fsf_close_wka_port(wka_port)) { ++ /* could not even send request, nothing to wait for */ + wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE; +- wake_up(&wka_port->completion_wq); ++ goto out; + } ++ wait_event(wka_port->closed, ++ wka_port->status == ZFCP_FC_WKA_PORT_OFFLINE); + out: + mutex_unlock(&wka_port->mutex); + } +@@ -193,13 +202,15 @@ static void zfcp_fc_wka_port_put(struct zfcp_fc_wka_port *wka_port) + if (atomic_dec_return(&wka_port->refcount) != 0) + return; + /* wait 10 milliseconds, other reqs might pop in */ +- schedule_delayed_work(&wka_port->work, HZ / 100); ++ queue_delayed_work(wka_port->adapter->work_queue, &wka_port->work, ++ msecs_to_jiffies(10)); + } + + static void zfcp_fc_wka_port_init(struct zfcp_fc_wka_port *wka_port, u32 d_id, + struct zfcp_adapter *adapter) + { +- init_waitqueue_head(&wka_port->completion_wq); ++ init_waitqueue_head(&wka_port->opened); ++ init_waitqueue_head(&wka_port->closed); + + wka_port->adapter = adapter; + wka_port->d_id = d_id; +diff --git a/drivers/s390/scsi/zfcp_fc.h b/drivers/s390/scsi/zfcp_fc.h +index 8aaf409ce9cba..97755407ce1b5 100644 +--- a/drivers/s390/scsi/zfcp_fc.h ++++ b/drivers/s390/scsi/zfcp_fc.h +@@ -185,7 +185,8 @@ enum zfcp_fc_wka_status { + /** + * struct zfcp_fc_wka_port - representation of well-known-address (WKA) FC port + * @adapter: Pointer to adapter structure this WKA port belongs to +- * @completion_wq: Wait for completion of open/close command ++ * @opened: Wait for completion of open command ++ * @closed: Wait for completion of close command + * @status: Current status of WKA port + * @refcount: Reference count to keep port open as long as it is in use + * @d_id: FC destination id or well-known-address +@@ -195,7 +196,8 @@ enum zfcp_fc_wka_status { + */ + struct zfcp_fc_wka_port { + struct zfcp_adapter *adapter; +- wait_queue_head_t completion_wq; ++ wait_queue_head_t opened; ++ wait_queue_head_t closed; + enum zfcp_fc_wka_status status; + atomic_t refcount; + u32 d_id; +diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c +index c1f979296c1a3..33b50b0990a06 100644 +--- a/drivers/s390/scsi/zfcp_fsf.c ++++ b/drivers/s390/scsi/zfcp_fsf.c +@@ -1907,7 +1907,7 @@ static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req) + wka_port->status = ZFCP_FC_WKA_PORT_ONLINE; + } + out: +- wake_up(&wka_port->completion_wq); ++ wake_up(&wka_port->opened); + } + + /** +@@ -1966,7 +1966,7 @@ static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req) + } + + wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE; +- wake_up(&wka_port->completion_wq); ++ wake_up(&wka_port->closed); + } + + /** +diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c +index e70f69f791db6..7974c1326d461 100644 +--- a/drivers/scsi/be2iscsi/be_main.c ++++ b/drivers/scsi/be2iscsi/be_main.c +@@ -5741,7 +5741,7 @@ static void beiscsi_remove(struct pci_dev *pcidev) + cancel_work_sync(&phba->sess_work); + + beiscsi_iface_destroy_default(phba); +- iscsi_host_remove(phba->shost); ++ iscsi_host_remove(phba->shost, false); + beiscsi_disable_port(phba, 1); + + /* after cancelling boot_work */ +diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c +index 2e5241d12dc3a..85b5aca4b4977 100644 +--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c ++++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c +@@ -909,7 +909,7 @@ void bnx2i_free_hba(struct bnx2i_hba *hba) + { + struct Scsi_Host *shost = hba->shost; + +- iscsi_host_remove(shost); ++ iscsi_host_remove(shost, false); + INIT_LIST_HEAD(&hba->ep_ofld_list); + INIT_LIST_HEAD(&hba->ep_active_list); + INIT_LIST_HEAD(&hba->ep_destroy_list); +diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c +index 4365d52c6430e..32abdf0fa9aab 100644 +--- a/drivers/scsi/cxgbi/libcxgbi.c ++++ b/drivers/scsi/cxgbi/libcxgbi.c +@@ -328,7 +328,7 @@ void cxgbi_hbas_remove(struct cxgbi_device *cdev) + chba = cdev->hbas[i]; + if (chba) { + cdev->hbas[i] = NULL; +- iscsi_host_remove(chba->shost); ++ iscsi_host_remove(chba->shost, false); + pci_dev_put(cdev->pdev); + iscsi_host_free(chba->shost); + } +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 15c7451fb30f9..fa22cb712be5a 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -518,6 +518,8 @@ struct hisi_sas_err_record_v3 { + #define CHNL_INT_STS_INT2_MSK BIT(3) + #define CHNL_WIDTH 4 + ++#define BAR_NO_V3_HW 5 ++ + enum { + DSM_FUNC_ERR_HANDLE_MSI = 0, + }; +@@ -4740,15 +4742,15 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) + struct sas_ha_struct *sha; + int rc, phy_nr, port_nr, i; + +- rc = pci_enable_device(pdev); ++ rc = pcim_enable_device(pdev); + if (rc) + goto err_out; + + pci_set_master(pdev); + +- rc = pci_request_regions(pdev, DRV_NAME); ++ rc = pcim_iomap_regions(pdev, 1 << BAR_NO_V3_HW, DRV_NAME); + if (rc) +- goto err_out_disable_device; ++ goto err_out; + + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (rc) +@@ -4756,20 +4758,20 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) + if (rc) { + dev_err(dev, "No usable DMA addressing method\n"); + rc = -ENODEV; +- goto err_out_regions; ++ goto err_out; + } + + shost = hisi_sas_shost_alloc_pci(pdev); + if (!shost) { + rc = -ENOMEM; +- goto err_out_regions; ++ goto err_out; + } + + sha = SHOST_TO_SAS_HA(shost); + hisi_hba = shost_priv(shost); + dev_set_drvdata(dev, sha); + +- hisi_hba->regs = pcim_iomap(pdev, 5, 0); ++ hisi_hba->regs = pcim_iomap_table(pdev)[BAR_NO_V3_HW]; + if (!hisi_hba->regs) { + dev_err(dev, "cannot map register\n"); + rc = -ENOMEM; +@@ -4861,10 +4863,6 @@ err_out_debugfs: + err_out_ha: + hisi_sas_free(hisi_hba); + scsi_host_put(shost); +-err_out_regions: +- pci_release_regions(pdev); +-err_out_disable_device: +- pci_disable_device(pdev); + err_out: + return rc; + } +@@ -4901,8 +4899,6 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev) + sas_remove_host(sha->core.shost); + + hisi_sas_v3_destroy_irqs(pdev, hisi_hba); +- pci_release_regions(pdev); +- pci_disable_device(pdev); + hisi_sas_free(hisi_hba); + debugfs_exit_v3_hw(hisi_hba); + scsi_host_put(shost); +diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c +index 1bc37593c88ff..0e52c6499eaf2 100644 +--- a/drivers/scsi/iscsi_tcp.c ++++ b/drivers/scsi/iscsi_tcp.c +@@ -898,7 +898,7 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, + remove_session: + iscsi_session_teardown(cls_session); + remove_host: +- iscsi_host_remove(shost); ++ iscsi_host_remove(shost, false); + free_host: + iscsi_host_free(shost); + return NULL; +@@ -915,7 +915,7 @@ static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session) + iscsi_tcp_r2tpool_free(cls_session->dd_data); + iscsi_session_teardown(cls_session); + +- iscsi_host_remove(shost); ++ iscsi_host_remove(shost, false); + iscsi_host_free(shost); + } + +diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c +index 0f2c7098f9d6e..78de36250b312 100644 +--- a/drivers/scsi/libiscsi.c ++++ b/drivers/scsi/libiscsi.c +@@ -2830,11 +2830,12 @@ static void iscsi_notify_host_removed(struct iscsi_cls_session *cls_session) + /** + * iscsi_host_remove - remove host and sessions + * @shost: scsi host ++ * @is_shutdown: true if called from a driver shutdown callout + * + * If there are any sessions left, this will initiate the removal and wait + * for the completion. + */ +-void iscsi_host_remove(struct Scsi_Host *shost) ++void iscsi_host_remove(struct Scsi_Host *shost, bool is_shutdown) + { + struct iscsi_host *ihost = shost_priv(shost); + unsigned long flags; +@@ -2843,7 +2844,11 @@ void iscsi_host_remove(struct Scsi_Host *shost) + ihost->state = ISCSI_HOST_REMOVED; + spin_unlock_irqrestore(&ihost->lock, flags); + +- iscsi_host_for_each_session(shost, iscsi_notify_host_removed); ++ if (!is_shutdown) ++ iscsi_host_for_each_session(shost, iscsi_notify_host_removed); ++ else ++ iscsi_host_for_each_session(shost, iscsi_force_destroy_session); ++ + wait_event_interruptible(ihost->session_removal_wq, + ihost->num_sessions == 0); + if (signal_pending(current)) +diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h +index 1044832b60549..f3bcb56e9ef28 100644 +--- a/drivers/scsi/lpfc/lpfc.h ++++ b/drivers/scsi/lpfc/lpfc.h +@@ -920,6 +920,10 @@ struct lpfc_hba { + (struct lpfc_vport *vport, + struct lpfc_io_buf *lpfc_cmd, + uint8_t tmo); ++ int (*lpfc_scsi_prep_task_mgmt_cmd) ++ (struct lpfc_vport *vport, ++ struct lpfc_io_buf *lpfc_cmd, ++ u64 lun, u8 task_mgmt_cmd); + + /* IOCB interface function jump table entries */ + int (*__lpfc_sli_issue_iocb) +@@ -1028,6 +1032,7 @@ struct lpfc_hba { + * Firmware supports Forced Link Speed + * capability + */ ++#define HBA_PCI_ERR 0x80000 /* The PCI slot is offline */ + #define HBA_FLOGI_ISSUED 0x100000 /* FLOGI was issued */ + #define HBA_CGN_RSVD1 0x200000 /* Reserved CGN flag */ + #define HBA_CGN_DAY_WRAP 0x400000 /* HBA Congestion info day wraps */ +@@ -1802,3 +1807,39 @@ static inline int lpfc_is_vmid_enabled(struct lpfc_hba *phba) + { + return phba->cfg_vmid_app_header || phba->cfg_vmid_priority_tagging; + } ++ ++static inline ++u8 get_job_ulpstatus(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) ++{ ++ if (phba->sli_rev == LPFC_SLI_REV4) ++ return bf_get(lpfc_wcqe_c_status, &iocbq->wcqe_cmpl); ++ else ++ return iocbq->iocb.ulpStatus; ++} ++ ++static inline ++u32 get_job_word4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) ++{ ++ if (phba->sli_rev == LPFC_SLI_REV4) ++ return iocbq->wcqe_cmpl.parameter; ++ else ++ return iocbq->iocb.un.ulpWord[4]; ++} ++ ++static inline ++u8 get_job_cmnd(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) ++{ ++ if (phba->sli_rev == LPFC_SLI_REV4) ++ return bf_get(wqe_cmnd, &iocbq->wqe.generic.wqe_com); ++ else ++ return iocbq->iocb.ulpCommand; ++} ++ ++static inline ++u16 get_job_ulpcontext(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) ++{ ++ if (phba->sli_rev == LPFC_SLI_REV4) ++ return bf_get(wqe_ctxt_tag, &iocbq->wqe.generic.wqe_com); ++ else ++ return iocbq->iocb.ulpContext; ++} +diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c +index fdf08cb572071..6688a575904f2 100644 +--- a/drivers/scsi/lpfc/lpfc_bsg.c ++++ b/drivers/scsi/lpfc/lpfc_bsg.c +@@ -325,7 +325,7 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, + + /* Close the timeout handler abort window */ + spin_lock_irqsave(&phba->hbalock, flags); +- cmdiocbq->iocb_flag &= ~LPFC_IO_CMD_OUTSTANDING; ++ cmdiocbq->cmd_flag &= ~LPFC_IO_CMD_OUTSTANDING; + spin_unlock_irqrestore(&phba->hbalock, flags); + + iocb = &dd_data->context_un.iocb; +@@ -481,11 +481,11 @@ lpfc_bsg_send_mgmt_cmd(struct bsg_job *job) + cmd->ulpOwner = OWN_CHIP; + cmdiocbq->vport = phba->pport; + cmdiocbq->context3 = bmp; +- cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; ++ cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC; + timeout = phba->fc_ratov * 2; + cmd->ulpTimeout = timeout; + +- cmdiocbq->iocb_cmpl = lpfc_bsg_send_mgmt_cmd_cmp; ++ cmdiocbq->cmd_cmpl = lpfc_bsg_send_mgmt_cmd_cmp; + cmdiocbq->context1 = dd_data; + cmdiocbq->context2 = cmp; + cmdiocbq->context3 = bmp; +@@ -516,9 +516,9 @@ lpfc_bsg_send_mgmt_cmd(struct bsg_job *job) + if (iocb_stat == IOCB_SUCCESS) { + spin_lock_irqsave(&phba->hbalock, flags); + /* make sure the I/O had not been completed yet */ +- if (cmdiocbq->iocb_flag & LPFC_IO_LIBDFC) { ++ if (cmdiocbq->cmd_flag & LPFC_IO_LIBDFC) { + /* open up abort window to timeout handler */ +- cmdiocbq->iocb_flag |= LPFC_IO_CMD_OUTSTANDING; ++ cmdiocbq->cmd_flag |= LPFC_IO_CMD_OUTSTANDING; + } + spin_unlock_irqrestore(&phba->hbalock, flags); + return 0; /* done for now */ +@@ -600,7 +600,7 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba, + + /* Close the timeout handler abort window */ + spin_lock_irqsave(&phba->hbalock, flags); +- cmdiocbq->iocb_flag &= ~LPFC_IO_CMD_OUTSTANDING; ++ cmdiocbq->cmd_flag &= ~LPFC_IO_CMD_OUTSTANDING; + spin_unlock_irqrestore(&phba->hbalock, flags); + + rsp = &rspiocbq->iocb; +@@ -726,10 +726,10 @@ lpfc_bsg_rport_els(struct bsg_job *job) + cmdiocbq->iocb.ulpContext = phba->sli4_hba.rpi_ids[rpi]; + else + cmdiocbq->iocb.ulpContext = rpi; +- cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; ++ cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC; + cmdiocbq->context1 = dd_data; + cmdiocbq->context_un.ndlp = ndlp; +- cmdiocbq->iocb_cmpl = lpfc_bsg_rport_els_cmp; ++ cmdiocbq->cmd_cmpl = lpfc_bsg_rport_els_cmp; + dd_data->type = TYPE_IOCB; + dd_data->set_job = job; + dd_data->context_un.iocb.cmdiocbq = cmdiocbq; +@@ -757,9 +757,9 @@ lpfc_bsg_rport_els(struct bsg_job *job) + if (rc == IOCB_SUCCESS) { + spin_lock_irqsave(&phba->hbalock, flags); + /* make sure the I/O had not been completed/released */ +- if (cmdiocbq->iocb_flag & LPFC_IO_LIBDFC) { ++ if (cmdiocbq->cmd_flag & LPFC_IO_LIBDFC) { + /* open up abort window to timeout handler */ +- cmdiocbq->iocb_flag |= LPFC_IO_CMD_OUTSTANDING; ++ cmdiocbq->cmd_flag |= LPFC_IO_CMD_OUTSTANDING; + } + spin_unlock_irqrestore(&phba->hbalock, flags); + return 0; /* done for now */ +@@ -1053,7 +1053,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + lpfc_in_buf_free(phba, + dmabuf); + } else { +- lpfc_post_buffer(phba, ++ lpfc_sli3_post_buffer(phba, + pring, + 1); + } +@@ -1061,7 +1061,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + default: + if (!(phba->sli3_options & + LPFC_SLI3_HBQ_ENABLED)) +- lpfc_post_buffer(phba, ++ lpfc_sli3_post_buffer(phba, + pring, + 1); + break; +@@ -1395,7 +1395,7 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba, + + /* Close the timeout handler abort window */ + spin_lock_irqsave(&phba->hbalock, flags); +- cmdiocbq->iocb_flag &= ~LPFC_IO_CMD_OUTSTANDING; ++ cmdiocbq->cmd_flag &= ~LPFC_IO_CMD_OUTSTANDING; + spin_unlock_irqrestore(&phba->hbalock, flags); + + ndlp = dd_data->context_un.iocb.ndlp; +@@ -1549,13 +1549,13 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag, + "2722 Xmit CT response on exchange x%x Data: x%x x%x x%x\n", + icmd->ulpContext, icmd->ulpIoTag, tag, phba->link_state); + +- ctiocb->iocb_flag |= LPFC_IO_LIBDFC; ++ ctiocb->cmd_flag |= LPFC_IO_LIBDFC; + ctiocb->vport = phba->pport; + ctiocb->context1 = dd_data; + ctiocb->context2 = cmp; + ctiocb->context3 = bmp; + ctiocb->context_un.ndlp = ndlp; +- ctiocb->iocb_cmpl = lpfc_issue_ct_rsp_cmp; ++ ctiocb->cmd_cmpl = lpfc_issue_ct_rsp_cmp; + + dd_data->type = TYPE_IOCB; + dd_data->set_job = job; +@@ -1582,9 +1582,9 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag, + if (rc == IOCB_SUCCESS) { + spin_lock_irqsave(&phba->hbalock, flags); + /* make sure the I/O had not been completed/released */ +- if (ctiocb->iocb_flag & LPFC_IO_LIBDFC) { ++ if (ctiocb->cmd_flag & LPFC_IO_LIBDFC) { + /* open up abort window to timeout handler */ +- ctiocb->iocb_flag |= LPFC_IO_CMD_OUTSTANDING; ++ ctiocb->cmd_flag |= LPFC_IO_CMD_OUTSTANDING; + } + spin_unlock_irqrestore(&phba->hbalock, flags); + return 0; /* done for now */ +@@ -2713,9 +2713,9 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi, + cmd->ulpClass = CLASS3; + cmd->ulpContext = rpi; + +- cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; ++ cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC; + cmdiocbq->vport = phba->pport; +- cmdiocbq->iocb_cmpl = NULL; ++ cmdiocbq->cmd_cmpl = NULL; + + iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq, + rspiocbq, +@@ -3286,10 +3286,10 @@ lpfc_bsg_diag_loopback_run(struct bsg_job *job) + cmdiocbq->sli4_xritag = NO_XRI; + cmd->unsli3.rcvsli3.ox_id = 0xffff; + } +- cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; +- cmdiocbq->iocb_flag |= LPFC_IO_LOOPBACK; ++ cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC; ++ cmdiocbq->cmd_flag |= LPFC_IO_LOOPBACK; + cmdiocbq->vport = phba->pport; +- cmdiocbq->iocb_cmpl = NULL; ++ cmdiocbq->cmd_cmpl = NULL; + iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq, + rspiocbq, (phba->fc_ratov * 2) + + LPFC_DRVR_TIMEOUT); +@@ -5273,11 +5273,11 @@ lpfc_menlo_cmd(struct bsg_job *job) + cmd->ulpClass = CLASS3; + cmd->ulpOwner = OWN_CHIP; + cmd->ulpLe = 1; /* Limited Edition */ +- cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; ++ cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC; + cmdiocbq->vport = phba->pport; + /* We want the firmware to timeout before we do */ + cmd->ulpTimeout = MENLO_TIMEOUT - 5; +- cmdiocbq->iocb_cmpl = lpfc_bsg_menlo_cmd_cmp; ++ cmdiocbq->cmd_cmpl = lpfc_bsg_menlo_cmd_cmp; + cmdiocbq->context1 = dd_data; + cmdiocbq->context2 = cmp; + cmdiocbq->context3 = bmp; +@@ -6001,7 +6001,7 @@ lpfc_bsg_timeout(struct bsg_job *job) + + spin_lock_irqsave(&phba->hbalock, flags); + /* make sure the I/O abort window is still open */ +- if (!(cmdiocb->iocb_flag & LPFC_IO_CMD_OUTSTANDING)) { ++ if (!(cmdiocb->cmd_flag & LPFC_IO_CMD_OUTSTANDING)) { + spin_unlock_irqrestore(&phba->hbalock, flags); + return -EAGAIN; + } +diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h +index c9770b1d2366a..f7bf589b63fb2 100644 +--- a/drivers/scsi/lpfc/lpfc_crtn.h ++++ b/drivers/scsi/lpfc/lpfc_crtn.h +@@ -129,6 +129,7 @@ void lpfc_disc_list_loopmap(struct lpfc_vport *); + void lpfc_disc_start(struct lpfc_vport *); + void lpfc_cleanup_discovery_resources(struct lpfc_vport *); + void lpfc_cleanup(struct lpfc_vport *); ++void lpfc_prep_embed_io(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_ncmd); + void lpfc_disc_timeout(struct timer_list *); + + int lpfc_unregister_fcf_prep(struct lpfc_hba *); +@@ -210,7 +211,7 @@ int lpfc_config_port_post(struct lpfc_hba *); + int lpfc_hba_down_prep(struct lpfc_hba *); + int lpfc_hba_down_post(struct lpfc_hba *); + void lpfc_hba_init(struct lpfc_hba *, uint32_t *); +-int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int); ++int lpfc_sli3_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt); + void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int); + int lpfc_online(struct lpfc_hba *); + void lpfc_unblock_mgmt_io(struct lpfc_hba *); +diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c +index dfcb7d4bd7fa1..19e2f8086a6da 100644 +--- a/drivers/scsi/lpfc/lpfc_ct.c ++++ b/drivers/scsi/lpfc/lpfc_ct.c +@@ -239,7 +239,7 @@ lpfc_ct_reject_event(struct lpfc_nodelist *ndlp, + cmdiocbq->context1 = lpfc_nlp_get(ndlp); + cmdiocbq->context2 = (uint8_t *)mp; + cmdiocbq->context3 = (uint8_t *)bmp; +- cmdiocbq->iocb_cmpl = lpfc_ct_unsol_cmpl; ++ cmdiocbq->cmd_cmpl = lpfc_ct_unsol_cmpl; + icmd->ulpContext = rx_id; /* Xri / rx_id */ + icmd->unsli3.rcvsli3.ox_id = ox_id; + icmd->un.ulpWord[3] = +@@ -370,7 +370,7 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + /* Not enough posted buffers; Try posting more buffers */ + phba->fc_stat.NoRcvBuf++; + if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) +- lpfc_post_buffer(phba, pring, 2); ++ lpfc_sli3_post_buffer(phba, pring, 2); + return; + } + +@@ -447,7 +447,7 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + lpfc_ct_unsol_buffer(phba, iocbq, mp, size); + lpfc_in_buf_free(phba, mp); + } +- lpfc_post_buffer(phba, pring, i); ++ lpfc_sli3_post_buffer(phba, pring, i); + } + list_del(&head); + } +@@ -652,7 +652,7 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, + "Data: x%x x%x\n", + ndlp->nlp_DID, icmd->ulpIoTag, + vport->port_state); +- geniocb->iocb_cmpl = cmpl; ++ geniocb->cmd_cmpl = cmpl; + geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT; + geniocb->vport = vport; + geniocb->retry = retry; +diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c +index 5f44a0763f37d..0d34a03164f53 100644 +--- a/drivers/scsi/lpfc/lpfc_els.c ++++ b/drivers/scsi/lpfc/lpfc_els.c +@@ -192,23 +192,23 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, + (elscmd == ELS_CMD_LOGO))) + switch (elscmd) { + case ELS_CMD_FLOGI: +- elsiocb->iocb_flag |= ++ elsiocb->cmd_flag |= + ((LPFC_ELS_ID_FLOGI << LPFC_FIP_ELS_ID_SHIFT) + & LPFC_FIP_ELS_ID_MASK); + break; + case ELS_CMD_FDISC: +- elsiocb->iocb_flag |= ++ elsiocb->cmd_flag |= + ((LPFC_ELS_ID_FDISC << LPFC_FIP_ELS_ID_SHIFT) + & LPFC_FIP_ELS_ID_MASK); + break; + case ELS_CMD_LOGO: +- elsiocb->iocb_flag |= ++ elsiocb->cmd_flag |= + ((LPFC_ELS_ID_LOGO << LPFC_FIP_ELS_ID_SHIFT) + & LPFC_FIP_ELS_ID_MASK); + break; + } + else +- elsiocb->iocb_flag &= ~LPFC_FIP_ELS_ID_MASK; ++ elsiocb->cmd_flag &= ~LPFC_FIP_ELS_ID_MASK; + + icmd = &elsiocb->iocb; + +@@ -1252,10 +1252,10 @@ lpfc_cmpl_els_link_down(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + "6445 ELS completes after LINK_DOWN: " + " Status %x/%x cmd x%x flg x%x\n", + irsp->ulpStatus, irsp->un.ulpWord[4], cmd, +- cmdiocb->iocb_flag); ++ cmdiocb->cmd_flag); + +- if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) { +- cmdiocb->iocb_flag &= ~LPFC_IO_FABRIC; ++ if (cmdiocb->cmd_flag & LPFC_IO_FABRIC) { ++ cmdiocb->cmd_flag &= ~LPFC_IO_FABRIC; + atomic_dec(&phba->fabric_iocb_count); + } + lpfc_els_free_iocb(phba, cmdiocb); +@@ -1370,7 +1370,7 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, + phba->fc_ratov = tmo; + + phba->fc_stat.elsXmitFLOGI++; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_flogi; + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, + "Issue FLOGI: opt:x%x", +@@ -1463,7 +1463,7 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba) + if (ndlp && ndlp->nlp_DID == Fabric_DID) { + if ((phba->pport->fc_flag & FC_PT2PT) && + !(phba->pport->fc_flag & FC_PT2PT_PLOGI)) +- iocb->fabric_iocb_cmpl = ++ iocb->fabric_cmd_cmpl = + lpfc_ignore_els_cmpl; + lpfc_sli_issue_abort_iotag(phba, pring, iocb, + NULL); +@@ -2226,7 +2226,7 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) + } + + phba->fc_stat.elsXmitPLOGI++; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_plogi; + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, + "Issue PLOGI: did:x%x refcnt %d", +@@ -2478,7 +2478,7 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, + /* For FCP support */ + npr->prliType = PRLI_FCP_TYPE; + npr->initiatorFunc = 1; +- elsiocb->iocb_flag |= LPFC_PRLI_FCP_REQ; ++ elsiocb->cmd_flag |= LPFC_PRLI_FCP_REQ; + + /* Remove FCP type - processed. */ + local_nlp_type &= ~NLP_FC4_FCP; +@@ -2512,14 +2512,14 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, + + npr_nvme->word1 = cpu_to_be32(npr_nvme->word1); + npr_nvme->word4 = cpu_to_be32(npr_nvme->word4); +- elsiocb->iocb_flag |= LPFC_PRLI_NVME_REQ; ++ elsiocb->cmd_flag |= LPFC_PRLI_NVME_REQ; + + /* Remove NVME type - processed. */ + local_nlp_type &= ~NLP_FC4_NVME; + } + + phba->fc_stat.elsXmitPRLI++; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_prli; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_prli; + spin_lock_irq(&ndlp->lock); + ndlp->nlp_flag |= NLP_PRLI_SND; + +@@ -2842,7 +2842,7 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, + ap->DID = be32_to_cpu(vport->fc_myDID); + + phba->fc_stat.elsXmitADISC++; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_adisc; + spin_lock_irq(&ndlp->lock); + ndlp->nlp_flag |= NLP_ADISC_SND; + spin_unlock_irq(&ndlp->lock); +@@ -3065,7 +3065,7 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, + memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name)); + + phba->fc_stat.elsXmitLOGO++; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_logo; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_logo; + spin_lock_irq(&ndlp->lock); + ndlp->nlp_flag |= NLP_LOGO_SND; + ndlp->nlp_flag &= ~NLP_ISSUE_LOGO; +@@ -3417,7 +3417,7 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry) + ndlp->nlp_DID, 0, 0); + + phba->fc_stat.elsXmitSCR++; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { + lpfc_els_free_iocb(phba, elsiocb); +@@ -3514,7 +3514,7 @@ lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry) + event->portid.rscn_fid[2] = nportid & 0x000000FF; + + phba->fc_stat.elsXmitRSCN++; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_cmd; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { + lpfc_els_free_iocb(phba, elsiocb); +@@ -3613,7 +3613,7 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) + ndlp->nlp_DID, 0, 0); + + phba->fc_stat.elsXmitFARPR++; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_cmd; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { + lpfc_els_free_iocb(phba, elsiocb); +@@ -3704,7 +3704,7 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry) + phba->cgn_reg_fpin); + + phba->cgn_fpin_frequency = LPFC_FPIN_INIT_FREQ; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { + lpfc_els_free_iocb(phba, elsiocb); +@@ -4154,7 +4154,7 @@ lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry) + ndlp->nlp_DID, phba->cgn_reg_signal, + phba->cgn_reg_fpin); + +- elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { + lpfc_els_free_iocb(phba, elsiocb); +@@ -4968,12 +4968,12 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb) + + /* context2 = cmd, context2->next = rsp, context3 = bpl */ + if (elsiocb->context2) { +- if (elsiocb->iocb_flag & LPFC_DELAY_MEM_FREE) { ++ if (elsiocb->cmd_flag & LPFC_DELAY_MEM_FREE) { + /* Firmware could still be in progress of DMAing + * payload, so don't free data buffer till after + * a hbeat. + */ +- elsiocb->iocb_flag &= ~LPFC_DELAY_MEM_FREE; ++ elsiocb->cmd_flag &= ~LPFC_DELAY_MEM_FREE; + buf_ptr = elsiocb->context2; + elsiocb->context2 = NULL; + if (buf_ptr) { +@@ -5480,9 +5480,9 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, + ndlp->nlp_flag & NLP_REG_LOGIN_SEND)) + ndlp->nlp_flag &= ~NLP_LOGO_ACC; + spin_unlock_irq(&ndlp->lock); +- elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_logo_acc; + } else { +- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + } + + phba->fc_stat.elsXmitACC++; +@@ -5577,7 +5577,7 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, + ndlp->nlp_DID, ndlp->nlp_flag, rejectError); + + phba->fc_stat.elsXmitLSRJT++; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { + lpfc_els_free_iocb(phba, elsiocb); +@@ -5657,7 +5657,7 @@ lpfc_issue_els_edc_rsp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, + "Issue EDC ACC: did:x%x flg:x%x refcnt %d", + ndlp->nlp_DID, ndlp->nlp_flag, + kref_read(&ndlp->kref)); +- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + + phba->fc_stat.elsXmitACC++; + elsiocb->context1 = lpfc_nlp_get(ndlp); +@@ -5750,7 +5750,7 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, + ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref)); + + phba->fc_stat.elsXmitACC++; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { + lpfc_els_free_iocb(phba, elsiocb); +@@ -5924,7 +5924,7 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, + ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref)); + + phba->fc_stat.elsXmitACC++; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { + lpfc_els_free_iocb(phba, elsiocb); +@@ -6025,7 +6025,7 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format, + ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref)); + + phba->fc_stat.elsXmitACC++; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { + lpfc_els_free_iocb(phba, elsiocb); +@@ -6139,7 +6139,7 @@ lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data, + ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref)); + + phba->fc_stat.elsXmitACC++; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { + lpfc_els_free_iocb(phba, elsiocb); +@@ -6803,7 +6803,7 @@ lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context, + rdp_context->page_a0, vport); + + rdp_res->length = cpu_to_be32(len - 8); +- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + + /* Now that we know the true size of the payload, update the BPL */ + bpl = (struct ulp_bde64 *) +@@ -6844,7 +6844,7 @@ error: + stat->un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + + phba->fc_stat.elsXmitLSRJT++; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { + lpfc_els_free_iocb(phba, elsiocb); +@@ -7066,7 +7066,7 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) + lcb_res->capability = lcb_context->capability; + lcb_res->lcb_frequency = lcb_context->frequency; + lcb_res->lcb_duration = lcb_context->duration; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + phba->fc_stat.elsXmitACC++; + + elsiocb->context1 = lpfc_nlp_get(ndlp); +@@ -7105,7 +7105,7 @@ error: + if (shdr_add_status == ADD_STATUS_OPERATION_ALREADY_ACTIVE) + stat->un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS; + +- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + phba->fc_stat.elsXmitLSRJT++; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { +@@ -8172,7 +8172,7 @@ lpfc_els_rsp_rls_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) + elsiocb->iotag, elsiocb->iocb.ulpContext, + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, + ndlp->nlp_rpi); +- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + phba->fc_stat.elsXmitACC++; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { +@@ -8324,7 +8324,7 @@ lpfc_els_rcv_rtv(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, + ndlp->nlp_rpi, + rtv_rsp->ratov, rtv_rsp->edtov, rtv_rsp->qtov); +- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + phba->fc_stat.elsXmitACC++; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { +@@ -8401,7 +8401,7 @@ lpfc_issue_els_rrq(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, + "Issue RRQ: did:x%x", + did, rrq->xritag, rrq->rxid); + elsiocb->context_un.rrq = rrq; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_rrq; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rrq; + + lpfc_nlp_get(ndlp); + elsiocb->context1 = ndlp; +@@ -8507,7 +8507,7 @@ lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize, + elsiocb->iotag, elsiocb->iocb.ulpContext, + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, + ndlp->nlp_rpi); +- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + phba->fc_stat.elsXmitACC++; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { +@@ -8947,7 +8947,7 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) + list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { + cmd = &piocb->iocb; + +- if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 || ++ if ((piocb->cmd_flag & LPFC_IO_LIBDFC) != 0 || + piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN || + piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN) + continue; +@@ -9060,13 +9060,13 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) + + /* First we need to issue aborts to outstanding cmds on txcmpl */ + list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { +- if (piocb->iocb_flag & LPFC_IO_LIBDFC) ++ if (piocb->cmd_flag & LPFC_IO_LIBDFC) + continue; + + if (piocb->vport != vport) + continue; + +- if (piocb->iocb_flag & LPFC_DRIVER_ABORTED) ++ if (piocb->cmd_flag & LPFC_DRIVER_ABORTED) + continue; + + /* On the ELS ring we can have ELS_REQUESTs or +@@ -9084,7 +9084,7 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) + * and avoid any retry logic. + */ + if (phba->link_state == LPFC_LINK_DOWN) +- piocb->iocb_cmpl = lpfc_cmpl_els_link_down; ++ piocb->cmd_cmpl = lpfc_cmpl_els_link_down; + } + if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) + list_add_tail(&piocb->dlist, &abort_list); +@@ -9119,9 +9119,8 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) + list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) { + cmd = &piocb->iocb; + +- if (piocb->iocb_flag & LPFC_IO_LIBDFC) { ++ if (piocb->cmd_flag & LPFC_IO_LIBDFC) + continue; +- } + + /* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */ + if (cmd->ulpCommand == CMD_QUE_RING_BUF_CN || +@@ -9766,7 +9765,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + payload_len = elsiocb->iocb.unsli3.rcvsli3.acc_len; + cmd = *payload; + if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0) +- lpfc_post_buffer(phba, pring, 1); ++ lpfc_sli3_post_buffer(phba, pring, 1); + + did = icmd->un.rcvels.remoteID; + if (icmd->ulpStatus) { +@@ -10239,7 +10238,7 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + phba->fc_stat.NoRcvBuf++; + /* Not enough posted buffers; Try posting more buffers */ + if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) +- lpfc_post_buffer(phba, pring, 0); ++ lpfc_sli3_post_buffer(phba, pring, 0); + return; + } + +@@ -10875,7 +10874,7 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, + lpfc_set_disctmo(vport); + + phba->fc_stat.elsXmitFDISC++; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_fdisc; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_fdisc; + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, + "Issue FDISC: did:x%x", +@@ -10999,7 +10998,7 @@ lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) + "Issue LOGO npiv did:x%x flg:x%x", + ndlp->nlp_DID, ndlp->nlp_flag, 0); + +- elsiocb->iocb_cmpl = lpfc_cmpl_els_npiv_logo; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_npiv_logo; + spin_lock_irq(&ndlp->lock); + ndlp->nlp_flag |= NLP_LOGO_SND; + spin_unlock_irq(&ndlp->lock); +@@ -11084,9 +11083,9 @@ repeat: + } + spin_unlock_irqrestore(&phba->hbalock, iflags); + if (iocb) { +- iocb->fabric_iocb_cmpl = iocb->iocb_cmpl; +- iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb; +- iocb->iocb_flag |= LPFC_IO_FABRIC; ++ iocb->fabric_cmd_cmpl = iocb->cmd_cmpl; ++ iocb->cmd_cmpl = lpfc_cmpl_fabric_iocb; ++ iocb->cmd_flag |= LPFC_IO_FABRIC; + + lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD, + "Fabric sched1: ste:x%x", +@@ -11095,13 +11094,13 @@ repeat: + ret = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, iocb, 0); + + if (ret == IOCB_ERROR) { +- iocb->iocb_cmpl = iocb->fabric_iocb_cmpl; +- iocb->fabric_iocb_cmpl = NULL; +- iocb->iocb_flag &= ~LPFC_IO_FABRIC; ++ iocb->cmd_cmpl = iocb->fabric_cmd_cmpl; ++ iocb->fabric_cmd_cmpl = NULL; ++ iocb->cmd_flag &= ~LPFC_IO_FABRIC; + cmd = &iocb->iocb; + cmd->ulpStatus = IOSTAT_LOCAL_REJECT; + cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; +- iocb->iocb_cmpl(phba, iocb, iocb); ++ iocb->cmd_cmpl(phba, iocb, iocb); + + atomic_dec(&phba->fabric_iocb_count); + goto repeat; +@@ -11157,8 +11156,8 @@ lpfc_block_fabric_iocbs(struct lpfc_hba *phba) + * @rspiocb: pointer to lpfc response iocb data structure. + * + * This routine is the callback function that is put to the fabric iocb's +- * callback function pointer (iocb->iocb_cmpl). The original iocb's callback +- * function pointer has been stored in iocb->fabric_iocb_cmpl. This callback ++ * callback function pointer (iocb->cmd_cmpl). The original iocb's callback ++ * function pointer has been stored in iocb->fabric_cmd_cmpl. This callback + * function first restores and invokes the original iocb's callback function + * and then invokes the lpfc_resume_fabric_iocbs() routine to issue the next + * fabric bound iocb from the driver internal fabric iocb list onto the wire. +@@ -11169,7 +11168,7 @@ lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + { + struct ls_rjt stat; + +- BUG_ON((cmdiocb->iocb_flag & LPFC_IO_FABRIC) != LPFC_IO_FABRIC); ++ WARN_ON((cmdiocb->cmd_flag & LPFC_IO_FABRIC) != LPFC_IO_FABRIC); + + switch (rspiocb->iocb.ulpStatus) { + case IOSTAT_NPORT_RJT: +@@ -11195,10 +11194,10 @@ lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + + BUG_ON(atomic_read(&phba->fabric_iocb_count) == 0); + +- cmdiocb->iocb_cmpl = cmdiocb->fabric_iocb_cmpl; +- cmdiocb->fabric_iocb_cmpl = NULL; +- cmdiocb->iocb_flag &= ~LPFC_IO_FABRIC; +- cmdiocb->iocb_cmpl(phba, cmdiocb, rspiocb); ++ cmdiocb->cmd_cmpl = cmdiocb->fabric_cmd_cmpl; ++ cmdiocb->fabric_cmd_cmpl = NULL; ++ cmdiocb->cmd_flag &= ~LPFC_IO_FABRIC; ++ cmdiocb->cmd_cmpl(phba, cmdiocb, rspiocb); + + atomic_dec(&phba->fabric_iocb_count); + if (!test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags)) { +@@ -11249,9 +11248,9 @@ lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb) + atomic_inc(&phba->fabric_iocb_count); + spin_unlock_irqrestore(&phba->hbalock, iflags); + if (ready) { +- iocb->fabric_iocb_cmpl = iocb->iocb_cmpl; +- iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb; +- iocb->iocb_flag |= LPFC_IO_FABRIC; ++ iocb->fabric_cmd_cmpl = iocb->cmd_cmpl; ++ iocb->cmd_cmpl = lpfc_cmpl_fabric_iocb; ++ iocb->cmd_flag |= LPFC_IO_FABRIC; + + lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD, + "Fabric sched2: ste:x%x", +@@ -11260,9 +11259,9 @@ lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb) + ret = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, iocb, 0); + + if (ret == IOCB_ERROR) { +- iocb->iocb_cmpl = iocb->fabric_iocb_cmpl; +- iocb->fabric_iocb_cmpl = NULL; +- iocb->iocb_flag &= ~LPFC_IO_FABRIC; ++ iocb->cmd_cmpl = iocb->fabric_cmd_cmpl; ++ iocb->fabric_cmd_cmpl = NULL; ++ iocb->cmd_flag &= ~LPFC_IO_FABRIC; + atomic_dec(&phba->fabric_iocb_count); + } + } else { +@@ -11655,7 +11654,7 @@ int lpfc_issue_els_qfpa(struct lpfc_vport *vport) + *((u32 *)(pcmd)) = ELS_CMD_QFPA; + pcmd += 4; + +- elsiocb->iocb_cmpl = lpfc_cmpl_els_qfpa; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_qfpa; + + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { +@@ -11738,7 +11737,7 @@ lpfc_vmid_uvem(struct lpfc_vport *vport, + } + inst_desc->word6 = cpu_to_be32(inst_desc->word6); + +- elsiocb->iocb_cmpl = lpfc_cmpl_els_uvem; ++ elsiocb->cmd_cmpl = lpfc_cmpl_els_uvem; + + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { +diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c +index 3bb7c2aa949f7..4bb0a15cfcc01 100644 +--- a/drivers/scsi/lpfc/lpfc_hbadisc.c ++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c +@@ -5349,6 +5349,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) + + rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); + if (rc == MBX_NOT_FINISHED) { ++ ndlp->nlp_flag &= ~NLP_UNREG_INP; + mempool_free(mbox, phba->mbox_mem_pool); + acc_plogi = 1; + } +diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h +index 824fc8c08840b..215fbf1c777ec 100644 +--- a/drivers/scsi/lpfc/lpfc_hw4.h ++++ b/drivers/scsi/lpfc/lpfc_hw4.h +@@ -60,6 +60,13 @@ + ((ptr)->name##_WORD = ((((value) & name##_MASK) << name##_SHIFT) | \ + ((ptr)->name##_WORD & ~(name##_MASK << name##_SHIFT)))) + ++#define get_wqe_reqtag(x) (((x)->wqe.words[9] >> 0) & 0xFFFF) ++ ++#define get_job_ulpword(x, y) ((x)->iocb.un.ulpWord[y]) ++ ++#define set_job_ulpstatus(x, y) bf_set(lpfc_wcqe_c_status, &(x)->wcqe_cmpl, y) ++#define set_job_ulpword4(x, y) ((&(x)->wcqe_cmpl)->parameter = y) ++ + struct dma_address { + uint32_t addr_lo; + uint32_t addr_hi; +diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c +index a2694fb32b5d9..6d04b3323eb7e 100644 +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -982,7 +982,7 @@ lpfc_hba_clean_txcmplq(struct lpfc_hba *phba) + spin_lock_irq(&pring->ring_lock); + list_for_each_entry_safe(piocb, next_iocb, + &pring->txcmplq, list) +- piocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; ++ piocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ; + list_splice_init(&pring->txcmplq, &completions); + pring->txcmplq_cnt = 0; + spin_unlock_irq(&pring->ring_lock); +@@ -1606,6 +1606,11 @@ void + lpfc_sli4_offline_eratt(struct lpfc_hba *phba) + { + spin_lock_irq(&phba->hbalock); ++ if (phba->link_state == LPFC_HBA_ERROR && ++ phba->hba_flag & HBA_PCI_ERR) { ++ spin_unlock_irq(&phba->hbalock); ++ return; ++ } + phba->link_state = LPFC_HBA_ERROR; + spin_unlock_irq(&phba->hbalock); + +@@ -1945,7 +1950,6 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) + if (pci_channel_offline(phba->pcidev)) { + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "3166 pci channel is offline\n"); +- lpfc_sli4_offline_eratt(phba); + return; + } + +@@ -2639,7 +2643,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) + } + + /** +- * lpfc_post_buffer - Post IOCB(s) with DMA buffer descriptor(s) to a IOCB ring ++ * lpfc_sli3_post_buffer - Post IOCB(s) with DMA buffer descriptor(s) to a IOCB ring + * @phba: pointer to lpfc hba data structure. + * @pring: pointer to a IOCB ring. + * @cnt: the number of IOCBs to be posted to the IOCB ring. +@@ -2651,7 +2655,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) + * The number of IOCBs NOT able to be posted to the IOCB ring. + **/ + int +-lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt) ++lpfc_sli3_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt) + { + IOCB_t *icmd; + struct lpfc_iocbq *iocb; +@@ -2757,7 +2761,7 @@ lpfc_post_rcv_buf(struct lpfc_hba *phba) + struct lpfc_sli *psli = &phba->sli; + + /* Ring 0, ELS / CT buffers */ +- lpfc_post_buffer(phba, &psli->sli3_ring[LPFC_ELS_RING], LPFC_BUF_RING0); ++ lpfc_sli3_post_buffer(phba, &psli->sli3_ring[LPFC_ELS_RING], LPFC_BUF_RING0); + /* Ring 2 - FCP no buffers needed */ + + return 0; +@@ -3643,6 +3647,7 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action) + struct lpfc_vport **vports; + struct Scsi_Host *shost; + int i; ++ int offline = 0; + + if (vport->fc_flag & FC_OFFLINE_MODE) + return; +@@ -3651,6 +3656,8 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action) + + lpfc_linkdown(phba); + ++ offline = pci_channel_offline(phba->pcidev); ++ + /* Issue an unreg_login to all nodes on all vports */ + vports = lpfc_create_vport_work_array(phba); + if (vports != NULL) { +@@ -3673,7 +3680,14 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action) + ndlp->nlp_flag &= ~NLP_NPR_ADISC; + spin_unlock_irq(&ndlp->lock); + +- lpfc_unreg_rpi(vports[i], ndlp); ++ if (offline) { ++ spin_lock_irq(&ndlp->lock); ++ ndlp->nlp_flag &= ~(NLP_UNREG_INP | ++ NLP_RPI_REGISTERED); ++ spin_unlock_irq(&ndlp->lock); ++ } else { ++ lpfc_unreg_rpi(vports[i], ndlp); ++ } + /* + * Whenever an SLI4 port goes offline, free the + * RPI. Get a new RPI when the adapter port +@@ -4201,8 +4215,7 @@ lpfc_io_buf_replenish(struct lpfc_hba *phba, struct list_head *cbuf) + qp = &phba->sli4_hba.hdwq[idx]; + lpfc_cmd->hdwq_no = idx; + lpfc_cmd->hdwq = qp; +- lpfc_cmd->cur_iocbq.wqe_cmpl = NULL; +- lpfc_cmd->cur_iocbq.iocb_cmpl = NULL; ++ lpfc_cmd->cur_iocbq.cmd_cmpl = NULL; + spin_lock(&qp->io_buf_list_put_lock); + list_add_tail(&lpfc_cmd->list, + &qp->lpfc_io_buf_list_put); +@@ -11951,7 +11964,7 @@ lpfc_sli_enable_msi(struct lpfc_hba *phba) + rc = pci_enable_msi(phba->pcidev); + if (!rc) + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, +- "0462 PCI enable MSI mode success.\n"); ++ "0012 PCI enable MSI mode success.\n"); + else { + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, + "0471 PCI enable MSI mode failed (%d)\n", rc); +@@ -14070,6 +14083,10 @@ lpfc_pci_resume_one_s3(struct device *dev_d) + return error; + } + ++ /* Init cpu_map array */ ++ lpfc_cpu_map_array_init(phba); ++ /* Init hba_eq_hdl array */ ++ lpfc_hba_eq_hdl_array_init(phba); + /* Configure and enable interrupt */ + intr_mode = lpfc_sli_enable_intr(phba, phba->intr_mode); + if (intr_mode == LPFC_INTR_ERROR) { +@@ -15023,14 +15040,17 @@ lpfc_io_error_detected_s4(struct pci_dev *pdev, pci_channel_state_t state) + lpfc_sli4_prep_dev_for_recover(phba); + return PCI_ERS_RESULT_CAN_RECOVER; + case pci_channel_io_frozen: ++ phba->hba_flag |= HBA_PCI_ERR; + /* Fatal error, prepare for slot reset */ + lpfc_sli4_prep_dev_for_reset(phba); + return PCI_ERS_RESULT_NEED_RESET; + case pci_channel_io_perm_failure: ++ phba->hba_flag |= HBA_PCI_ERR; + /* Permanent failure, prepare for device down */ + lpfc_sli4_prep_dev_for_perm_failure(phba); + return PCI_ERS_RESULT_DISCONNECT; + default: ++ phba->hba_flag |= HBA_PCI_ERR; + /* Unknown state, prepare and request slot reset */ + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2825 Unknown PCI error state: x%x\n", state); +@@ -15074,6 +15094,7 @@ lpfc_io_slot_reset_s4(struct pci_dev *pdev) + + pci_restore_state(pdev); + ++ phba->hba_flag &= ~HBA_PCI_ERR; + /* + * As the new kernel behavior of pci_restore_state() API call clears + * device saved_state flag, need to save the restored state again. +@@ -15098,6 +15119,7 @@ lpfc_io_slot_reset_s4(struct pci_dev *pdev) + return PCI_ERS_RESULT_DISCONNECT; + } else + phba->intr_mode = intr_mode; ++ lpfc_cpu_affinity_check(phba, phba->cfg_irq_chann); + + /* Log the current active interrupt mode */ + lpfc_log_intr_mode(phba, phba->intr_mode); +@@ -15299,6 +15321,10 @@ lpfc_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) + struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; + pci_ers_result_t rc = PCI_ERS_RESULT_DISCONNECT; + ++ if (phba->link_state == LPFC_HBA_ERROR && ++ phba->hba_flag & HBA_IOQ_FLUSH) ++ return PCI_ERS_RESULT_NEED_RESET; ++ + switch (phba->pci_dev_grp) { + case LPFC_PCI_DEV_LP: + rc = lpfc_io_error_detected_s3(pdev, state); +diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c +index 2bd35a7424c25..e788610bc996a 100644 +--- a/drivers/scsi/lpfc/lpfc_nportdisc.c ++++ b/drivers/scsi/lpfc/lpfc_nportdisc.c +@@ -2139,9 +2139,9 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, + npr = NULL; + nvpr = NULL; + temp_ptr = lpfc_check_elscmpl_iocb(phba, cmdiocb, rspiocb); +- if (cmdiocb->iocb_flag & LPFC_PRLI_FCP_REQ) ++ if (cmdiocb->cmd_flag & LPFC_PRLI_FCP_REQ) + npr = (PRLI *) temp_ptr; +- else if (cmdiocb->iocb_flag & LPFC_PRLI_NVME_REQ) ++ else if (cmdiocb->cmd_flag & LPFC_PRLI_NVME_REQ) + nvpr = (struct lpfc_nvme_prli *) temp_ptr; + + irsp = &rspiocb->iocb; +diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c +index 4fb3dc5092f54..c74b2187dbada 100644 +--- a/drivers/scsi/lpfc/lpfc_nvme.c ++++ b/drivers/scsi/lpfc/lpfc_nvme.c +@@ -352,11 +352,12 @@ __lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport, + + static void + lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, +- struct lpfc_wcqe_complete *wcqe) ++ struct lpfc_iocbq *rspwqe) + { + struct lpfc_vport *vport = cmdwqe->vport; + struct lpfc_nvme_lport *lport; + uint32_t status; ++ struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; + + status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK; + +@@ -380,7 +381,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, + struct lpfc_dmabuf *inp, + struct nvmefc_ls_req *pnvme_lsreq, + void (*cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, +- struct lpfc_wcqe_complete *), ++ struct lpfc_iocbq *), + struct lpfc_nodelist *ndlp, uint32_t num_entry, + uint32_t tmo, uint8_t retry) + { +@@ -401,7 +402,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, + memset(wqe, 0, sizeof(union lpfc_wqe)); + + genwqe->context3 = (uint8_t *)bmp; +- genwqe->iocb_flag |= LPFC_IO_NVME_LS; ++ genwqe->cmd_flag |= LPFC_IO_NVME_LS; + + /* Save for completion so we can release these resources */ + genwqe->context1 = lpfc_nlp_get(ndlp); +@@ -432,7 +433,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, + first_len = xmit_len; + } + +- genwqe->rsvd2 = num_entry; ++ genwqe->num_bdes = num_entry; + genwqe->hba_wqidx = 0; + + /* Words 0 - 2 */ +@@ -483,8 +484,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, + + + /* Issue GEN REQ WQE for NPORT <did> */ +- genwqe->wqe_cmpl = cmpl; +- genwqe->iocb_cmpl = NULL; ++ genwqe->cmd_cmpl = cmpl; + genwqe->drvrTimeout = tmo + LPFC_DRVR_TIMEOUT; + genwqe->vport = vport; + genwqe->retry = retry; +@@ -534,7 +534,7 @@ __lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, + struct nvmefc_ls_req *pnvme_lsreq, + void (*gen_req_cmp)(struct lpfc_hba *phba, + struct lpfc_iocbq *cmdwqe, +- struct lpfc_wcqe_complete *wcqe)) ++ struct lpfc_iocbq *rspwqe)) + { + struct lpfc_dmabuf *bmp; + struct ulp_bde64 *bpl; +@@ -722,7 +722,7 @@ __lpfc_nvme_ls_abort(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, + spin_lock(&pring->ring_lock); + list_for_each_entry_safe(wqe, next_wqe, &pring->txcmplq, list) { + if (wqe->context2 == pnvme_lsreq) { +- wqe->iocb_flag |= LPFC_DRIVER_ABORTED; ++ wqe->cmd_flag |= LPFC_DRIVER_ABORTED; + foundit = true; + break; + } +@@ -906,7 +906,7 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport, + + + /* +- * lpfc_nvme_io_cmd_wqe_cmpl - Complete an NVME-over-FCP IO ++ * lpfc_nvme_io_cmd_cmpl - Complete an NVME-over-FCP IO + * + * Driver registers this routine as it io request handler. This + * routine issues an fcp WQE with data from the @lpfc_nvme_fcpreq +@@ -917,11 +917,12 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport, + * TODO: What are the failure codes. + **/ + static void +-lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, +- struct lpfc_wcqe_complete *wcqe) ++lpfc_nvme_io_cmd_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, ++ struct lpfc_iocbq *pwqeOut) + { + struct lpfc_io_buf *lpfc_ncmd = + (struct lpfc_io_buf *)pwqeIn->context1; ++ struct lpfc_wcqe_complete *wcqe = &pwqeOut->wcqe_cmpl; + struct lpfc_vport *vport = pwqeIn->vport; + struct nvmefc_fcp_req *nCmd; + struct nvme_fc_ersp_iu *ep; +@@ -937,6 +938,7 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS + int cpu; + #endif ++ int offline = 0; + + /* Sanity check on return of outstanding command */ + if (!lpfc_ncmd) { +@@ -1098,11 +1100,12 @@ out_err: + nCmd->transferred_length = 0; + nCmd->rcv_rsplen = 0; + nCmd->status = NVME_SC_INTERNAL; ++ offline = pci_channel_offline(vport->phba->pcidev); + } + } + + /* pick up SLI4 exhange busy condition */ +- if (bf_get(lpfc_wcqe_c_xb, wcqe)) ++ if (bf_get(lpfc_wcqe_c_xb, wcqe) && !offline) + lpfc_ncmd->flags |= LPFC_SBUF_XBUSY; + else + lpfc_ncmd->flags &= ~LPFC_SBUF_XBUSY; +@@ -1871,7 +1874,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, + } + + /* Don't abort IOs no longer on the pending queue. */ +- if (!(nvmereq_wqe->iocb_flag & LPFC_IO_ON_TXCMPLQ)) { ++ if (!(nvmereq_wqe->cmd_flag & LPFC_IO_ON_TXCMPLQ)) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "6142 NVME IO req x%px not queued - skipping " + "abort req xri x%x\n", +@@ -1885,7 +1888,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, + nvmereq_wqe->hba_wqidx, pnvme_rport->port_id); + + /* Outstanding abort is in progress */ +- if (nvmereq_wqe->iocb_flag & LPFC_DRIVER_ABORTED) { ++ if (nvmereq_wqe->cmd_flag & LPFC_DRIVER_ABORTED) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "6144 Outstanding NVME I/O Abort Request " + "still pending on nvme_fcreq x%px, " +@@ -1980,8 +1983,8 @@ lpfc_get_nvme_buf(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, + /* Setup key fields in buffer that may have been changed + * if other protocols used this buffer. + */ +- pwqeq->iocb_flag = LPFC_IO_NVME; +- pwqeq->wqe_cmpl = lpfc_nvme_io_cmd_wqe_cmpl; ++ pwqeq->cmd_flag = LPFC_IO_NVME; ++ pwqeq->cmd_cmpl = lpfc_nvme_io_cmd_cmpl; + lpfc_ncmd->start_time = jiffies; + lpfc_ncmd->flags = 0; + +@@ -2174,6 +2177,10 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport, + abts_nvme = 0; + for (i = 0; i < phba->cfg_hdw_queue; i++) { + qp = &phba->sli4_hba.hdwq[i]; ++ if (!vport || !vport->localport || ++ !qp || !qp->io_wq) ++ return; ++ + pring = qp->io_wq->pring; + if (!pring) + continue; +@@ -2181,6 +2188,10 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport, + abts_scsi += qp->abts_scsi_io_bufs; + abts_nvme += qp->abts_nvme_io_bufs; + } ++ if (!vport || !vport->localport || ++ vport->phba->hba_flag & HBA_PCI_ERR) ++ return; ++ + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "6176 Lport x%px Localport x%px wait " + "timed out. Pending %d [%d:%d]. " +@@ -2220,6 +2231,8 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport) + return; + + localport = vport->localport; ++ if (!localport) ++ return; + lport = (struct lpfc_nvme_lport *)localport->private; + + lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME, +@@ -2536,7 +2549,8 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) + * return values is ignored. The upcall is a courtesy to the + * transport. + */ +- if (vport->load_flag & FC_UNLOADING) ++ if (vport->load_flag & FC_UNLOADING || ++ unlikely(vport->phba->hba_flag & HBA_PCI_ERR)) + (void)nvme_fc_set_remoteport_devloss(remoteport, 0); + + ret = nvme_fc_unregister_remoteport(remoteport); +@@ -2564,6 +2578,42 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) + vport->localport, ndlp->rport, ndlp->nlp_DID); + } + ++/** ++ * lpfc_sli4_nvme_pci_offline_aborted - Fast-path process of NVME xri abort ++ * @phba: pointer to lpfc hba data structure. ++ * @lpfc_ncmd: The nvme job structure for the request being aborted. ++ * ++ * This routine is invoked by the worker thread to process a SLI4 fast-path ++ * NVME aborted xri. Aborted NVME IO commands are completed to the transport ++ * here. ++ **/ ++void ++lpfc_sli4_nvme_pci_offline_aborted(struct lpfc_hba *phba, ++ struct lpfc_io_buf *lpfc_ncmd) ++{ ++ struct nvmefc_fcp_req *nvme_cmd = NULL; ++ ++ lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS, ++ "6533 %s nvme_cmd %p tag x%x abort complete and " ++ "xri released\n", __func__, ++ lpfc_ncmd->nvmeCmd, ++ lpfc_ncmd->cur_iocbq.iotag); ++ ++ /* Aborted NVME commands are required to not complete ++ * before the abort exchange command fully completes. ++ * Once completed, it is available via the put list. ++ */ ++ if (lpfc_ncmd->nvmeCmd) { ++ nvme_cmd = lpfc_ncmd->nvmeCmd; ++ nvme_cmd->transferred_length = 0; ++ nvme_cmd->rcv_rsplen = 0; ++ nvme_cmd->status = NVME_SC_INTERNAL; ++ nvme_cmd->done(nvme_cmd); ++ lpfc_ncmd->nvmeCmd = NULL; ++ } ++ lpfc_release_nvme_buf(phba, lpfc_ncmd); ++} ++ + /** + * lpfc_sli4_nvme_xri_aborted - Fast-path process of NVME xri abort + * @phba: pointer to lpfc hba data structure. +@@ -2700,6 +2750,7 @@ lpfc_nvme_cancel_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, + if (phba->sli.sli_flag & LPFC_SLI_ACTIVE) + bf_set(lpfc_wcqe_c_xb, wcqep, 1); + +- (pwqeIn->wqe_cmpl)(phba, pwqeIn, wcqep); ++ memcpy(&pwqeIn->wcqe_cmpl, wcqep, sizeof(*wcqep)); ++ (pwqeIn->cmd_cmpl)(phba, pwqeIn, pwqeIn); + #endif + } +diff --git a/drivers/scsi/lpfc/lpfc_nvme.h b/drivers/scsi/lpfc/lpfc_nvme.h +index cc54ffb5c2058..d7698977725e0 100644 +--- a/drivers/scsi/lpfc/lpfc_nvme.h ++++ b/drivers/scsi/lpfc/lpfc_nvme.h +@@ -234,7 +234,7 @@ int __lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, + struct nvmefc_ls_req *pnvme_lsreq, + void (*gen_req_cmp)(struct lpfc_hba *phba, + struct lpfc_iocbq *cmdwqe, +- struct lpfc_wcqe_complete *wcqe)); ++ struct lpfc_iocbq *rspwqe)); + void __lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport, + struct lpfc_iocbq *cmdwqe, struct lpfc_wcqe_complete *wcqe); + int __lpfc_nvme_ls_abort(struct lpfc_vport *vport, +@@ -248,6 +248,6 @@ int __lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg, + struct nvmefc_ls_rsp *ls_rsp, + void (*xmt_ls_rsp_cmp)(struct lpfc_hba *phba, + struct lpfc_iocbq *cmdwqe, +- struct lpfc_wcqe_complete *wcqe)); ++ struct lpfc_iocbq *rspwqe)); + void __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, +- struct lpfc_iocbq *cmdwqe, struct lpfc_wcqe_complete *wcqe); ++ struct lpfc_iocbq *cmdwqe, struct lpfc_iocbq *rspwqe); +diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c +index 6e3dd0b9bcfa9..5188cc8e2413f 100644 +--- a/drivers/scsi/lpfc/lpfc_nvmet.c ++++ b/drivers/scsi/lpfc/lpfc_nvmet.c +@@ -285,7 +285,7 @@ lpfc_nvmet_defer_release(struct lpfc_hba *phba, + * transmission of an NVME LS response. + * @phba: Pointer to HBA context object. + * @cmdwqe: Pointer to driver command WQE object. +- * @wcqe: Pointer to driver response CQE object. ++ * @rspwqe: Pointer to driver response WQE object. + * + * The function is called from SLI ring event handler with no + * lock held. The function frees memory resources used for the command +@@ -293,9 +293,10 @@ lpfc_nvmet_defer_release(struct lpfc_hba *phba, + **/ + void + __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, +- struct lpfc_wcqe_complete *wcqe) ++ struct lpfc_iocbq *rspwqe) + { + struct lpfc_async_xchg_ctx *axchg = cmdwqe->context2; ++ struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; + struct nvmefc_ls_rsp *ls_rsp = &axchg->ls_rsp; + uint32_t status, result; + +@@ -331,7 +332,7 @@ __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, + * lpfc_nvmet_xmt_ls_rsp_cmp - Completion handler for LS Response + * @phba: Pointer to HBA context object. + * @cmdwqe: Pointer to driver command WQE object. +- * @wcqe: Pointer to driver response CQE object. ++ * @rspwqe: Pointer to driver response WQE object. + * + * The function is called from SLI ring event handler with no + * lock held. This function is the completion handler for NVME LS commands +@@ -340,10 +341,11 @@ __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, + **/ + static void + lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, +- struct lpfc_wcqe_complete *wcqe) ++ struct lpfc_iocbq *rspwqe) + { + struct lpfc_nvmet_tgtport *tgtp; + uint32_t status, result; ++ struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; + + if (!phba->targetport) + goto finish; +@@ -365,7 +367,7 @@ lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, + } + + finish: +- __lpfc_nvme_xmt_ls_rsp_cmp(phba, cmdwqe, wcqe); ++ __lpfc_nvme_xmt_ls_rsp_cmp(phba, cmdwqe, rspwqe); + } + + /** +@@ -707,7 +709,7 @@ out: + * lpfc_nvmet_xmt_fcp_op_cmp - Completion handler for FCP Response + * @phba: Pointer to HBA context object. + * @cmdwqe: Pointer to driver command WQE object. +- * @wcqe: Pointer to driver response CQE object. ++ * @rspwqe: Pointer to driver response WQE object. + * + * The function is called from SLI ring event handler with no + * lock held. This function is the completion handler for NVME FCP commands +@@ -715,12 +717,13 @@ out: + **/ + static void + lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, +- struct lpfc_wcqe_complete *wcqe) ++ struct lpfc_iocbq *rspwqe) + { + struct lpfc_nvmet_tgtport *tgtp; + struct nvmefc_tgt_fcp_req *rsp; + struct lpfc_async_xchg_ctx *ctxp; + uint32_t status, result, op, start_clean, logerr; ++ struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS + int id; + #endif +@@ -817,7 +820,7 @@ lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, + /* lpfc_nvmet_xmt_fcp_release() will recycle the context */ + } else { + ctxp->entry_cnt++; +- start_clean = offsetof(struct lpfc_iocbq, iocb_flag); ++ start_clean = offsetof(struct lpfc_iocbq, cmd_flag); + memset(((char *)cmdwqe) + start_clean, 0, + (sizeof(struct lpfc_iocbq) - start_clean)); + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS +@@ -862,7 +865,7 @@ __lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg, + struct nvmefc_ls_rsp *ls_rsp, + void (*xmt_ls_rsp_cmp)(struct lpfc_hba *phba, + struct lpfc_iocbq *cmdwqe, +- struct lpfc_wcqe_complete *wcqe)) ++ struct lpfc_iocbq *rspwqe)) + { + struct lpfc_hba *phba = axchg->phba; + struct hbq_dmabuf *nvmebuf = (struct hbq_dmabuf *)axchg->rqb_buffer; +@@ -898,7 +901,7 @@ __lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg, + } + + /* Save numBdes for bpl2sgl */ +- nvmewqeq->rsvd2 = 1; ++ nvmewqeq->num_bdes = 1; + nvmewqeq->hba_wqidx = 0; + nvmewqeq->context3 = &dmabuf; + dmabuf.virt = &bpl; +@@ -913,8 +916,7 @@ __lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg, + * be referenced after it returns back to this routine. + */ + +- nvmewqeq->wqe_cmpl = xmt_ls_rsp_cmp; +- nvmewqeq->iocb_cmpl = NULL; ++ nvmewqeq->cmd_cmpl = xmt_ls_rsp_cmp; + nvmewqeq->context2 = axchg; + + lpfc_nvmeio_data(phba, "NVMEx LS RSP: xri x%x wqidx x%x len x%x\n", +@@ -1072,10 +1074,9 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport, + goto aerr; + } + +- nvmewqeq->wqe_cmpl = lpfc_nvmet_xmt_fcp_op_cmp; +- nvmewqeq->iocb_cmpl = NULL; ++ nvmewqeq->cmd_cmpl = lpfc_nvmet_xmt_fcp_op_cmp; + nvmewqeq->context2 = ctxp; +- nvmewqeq->iocb_flag |= LPFC_IO_NVMET; ++ nvmewqeq->cmd_flag |= LPFC_IO_NVMET; + ctxp->wqeq->hba_wqidx = rsp->hwqid; + + lpfc_nvmeio_data(phba, "NVMET FCP CMND: xri x%x op x%x len x%x\n", +@@ -1275,7 +1276,7 @@ lpfc_nvmet_defer_rcv(struct nvmet_fc_target_port *tgtport, + * lpfc_nvmet_ls_req_cmp - completion handler for a nvme ls request + * @phba: Pointer to HBA context object + * @cmdwqe: Pointer to driver command WQE object. +- * @wcqe: Pointer to driver response CQE object. ++ * @rspwqe: Pointer to driver response WQE object. + * + * This function is the completion handler for NVME LS requests. + * The function updates any states and statistics, then calls the +@@ -1283,8 +1284,9 @@ lpfc_nvmet_defer_rcv(struct nvmet_fc_target_port *tgtport, + **/ + static void + lpfc_nvmet_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, +- struct lpfc_wcqe_complete *wcqe) ++ struct lpfc_iocbq *rspwqe) + { ++ struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; + __lpfc_nvme_ls_req_cmp(phba, cmdwqe->vport, cmdwqe, wcqe); + } + +@@ -1581,7 +1583,7 @@ lpfc_nvmet_setup_io_context(struct lpfc_hba *phba) + "6406 Ran out of NVMET iocb/WQEs\n"); + return -ENOMEM; + } +- ctx_buf->iocbq->iocb_flag = LPFC_IO_NVMET; ++ ctx_buf->iocbq->cmd_flag = LPFC_IO_NVMET; + nvmewqe = ctx_buf->iocbq; + wqe = &nvmewqe->wqe; + +@@ -2027,8 +2029,10 @@ lpfc_nvmet_wqfull_flush(struct lpfc_hba *phba, struct lpfc_queue *wq, + list_del(&nvmewqeq->list); + spin_unlock_irqrestore(&pring->ring_lock, + iflags); ++ memcpy(&nvmewqeq->wcqe_cmpl, wcqep, ++ sizeof(*wcqep)); + lpfc_nvmet_xmt_fcp_op_cmp(phba, nvmewqeq, +- wcqep); ++ nvmewqeq); + return; + } + continue; +@@ -2036,7 +2040,8 @@ lpfc_nvmet_wqfull_flush(struct lpfc_hba *phba, struct lpfc_queue *wq, + /* Flush all IOs */ + list_del(&nvmewqeq->list); + spin_unlock_irqrestore(&pring->ring_lock, iflags); +- lpfc_nvmet_xmt_fcp_op_cmp(phba, nvmewqeq, wcqep); ++ memcpy(&nvmewqeq->wcqe_cmpl, wcqep, sizeof(*wcqep)); ++ lpfc_nvmet_xmt_fcp_op_cmp(phba, nvmewqeq, nvmewqeq); + spin_lock_irqsave(&pring->ring_lock, iflags); + } + } +@@ -2676,7 +2681,7 @@ lpfc_nvmet_prep_ls_wqe(struct lpfc_hba *phba, + nvmewqe->retry = 1; + nvmewqe->vport = phba->pport; + nvmewqe->drvrTimeout = (phba->fc_ratov * 3) + LPFC_DRVR_TIMEOUT; +- nvmewqe->iocb_flag |= LPFC_IO_NVME_LS; ++ nvmewqe->cmd_flag |= LPFC_IO_NVME_LS; + + /* Xmit NVMET response to remote NPORT <did> */ + lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC, +@@ -3033,7 +3038,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, + * lpfc_nvmet_sol_fcp_abort_cmp - Completion handler for ABTS + * @phba: Pointer to HBA context object. + * @cmdwqe: Pointer to driver command WQE object. +- * @wcqe: Pointer to driver response CQE object. ++ * @rspwqe: Pointer to driver response WQE object. + * + * The function is called from SLI ring event handler with no + * lock held. This function is the completion handler for NVME ABTS for FCP cmds +@@ -3041,13 +3046,14 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, + **/ + static void + lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, +- struct lpfc_wcqe_complete *wcqe) ++ struct lpfc_iocbq *rspwqe) + { + struct lpfc_async_xchg_ctx *ctxp; + struct lpfc_nvmet_tgtport *tgtp; + uint32_t result; + unsigned long flags; + bool released = false; ++ struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; + + ctxp = cmdwqe->context2; + result = wcqe->parameter; +@@ -3102,7 +3108,7 @@ lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, + * lpfc_nvmet_unsol_fcp_abort_cmp - Completion handler for ABTS + * @phba: Pointer to HBA context object. + * @cmdwqe: Pointer to driver command WQE object. +- * @wcqe: Pointer to driver response CQE object. ++ * @rspwqe: Pointer to driver response WQE object. + * + * The function is called from SLI ring event handler with no + * lock held. This function is the completion handler for NVME ABTS for FCP cmds +@@ -3110,13 +3116,14 @@ lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, + **/ + static void + lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, +- struct lpfc_wcqe_complete *wcqe) ++ struct lpfc_iocbq *rspwqe) + { + struct lpfc_async_xchg_ctx *ctxp; + struct lpfc_nvmet_tgtport *tgtp; + unsigned long flags; + uint32_t result; + bool released = false; ++ struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; + + ctxp = cmdwqe->context2; + result = wcqe->parameter; +@@ -3183,7 +3190,7 @@ lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, + * lpfc_nvmet_xmt_ls_abort_cmp - Completion handler for ABTS + * @phba: Pointer to HBA context object. + * @cmdwqe: Pointer to driver command WQE object. +- * @wcqe: Pointer to driver response CQE object. ++ * @rspwqe: Pointer to driver response WQE object. + * + * The function is called from SLI ring event handler with no + * lock held. This function is the completion handler for NVME ABTS for LS cmds +@@ -3191,11 +3198,12 @@ lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, + **/ + static void + lpfc_nvmet_xmt_ls_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, +- struct lpfc_wcqe_complete *wcqe) ++ struct lpfc_iocbq *rspwqe) + { + struct lpfc_async_xchg_ctx *ctxp; + struct lpfc_nvmet_tgtport *tgtp; + uint32_t result; ++ struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; + + ctxp = cmdwqe->context2; + result = wcqe->parameter; +@@ -3319,7 +3327,7 @@ lpfc_nvmet_unsol_issue_abort(struct lpfc_hba *phba, + abts_wqeq->context1 = ndlp; + abts_wqeq->context2 = ctxp; + abts_wqeq->context3 = NULL; +- abts_wqeq->rsvd2 = 0; ++ abts_wqeq->num_bdes = 0; + /* hba_wqidx should already be setup from command we are aborting */ + abts_wqeq->iocb.ulpCommand = CMD_XMIT_SEQUENCE64_CR; + abts_wqeq->iocb.ulpLe = 1; +@@ -3448,7 +3456,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba, + } + + /* Outstanding abort is in progress */ +- if (abts_wqeq->iocb_flag & LPFC_DRIVER_ABORTED) { ++ if (abts_wqeq->cmd_flag & LPFC_DRIVER_ABORTED) { + spin_unlock_irqrestore(&phba->hbalock, flags); + atomic_inc(&tgtp->xmt_abort_rsp_error); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, +@@ -3463,15 +3471,14 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba, + } + + /* Ready - mark outstanding as aborted by driver. */ +- abts_wqeq->iocb_flag |= LPFC_DRIVER_ABORTED; ++ abts_wqeq->cmd_flag |= LPFC_DRIVER_ABORTED; + + lpfc_nvmet_prep_abort_wqe(abts_wqeq, ctxp->wqeq->sli4_xritag, opt); + + /* ABTS WQE must go to the same WQ as the WQE to be aborted */ + abts_wqeq->hba_wqidx = ctxp->wqeq->hba_wqidx; +- abts_wqeq->wqe_cmpl = lpfc_nvmet_sol_fcp_abort_cmp; +- abts_wqeq->iocb_cmpl = NULL; +- abts_wqeq->iocb_flag |= LPFC_IO_NVME; ++ abts_wqeq->cmd_cmpl = lpfc_nvmet_sol_fcp_abort_cmp; ++ abts_wqeq->cmd_flag |= LPFC_IO_NVME; + abts_wqeq->context2 = ctxp; + abts_wqeq->vport = phba->pport; + if (!ctxp->hdwq) +@@ -3528,9 +3535,8 @@ lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *phba, + + spin_lock_irqsave(&phba->hbalock, flags); + abts_wqeq = ctxp->wqeq; +- abts_wqeq->wqe_cmpl = lpfc_nvmet_unsol_fcp_abort_cmp; +- abts_wqeq->iocb_cmpl = NULL; +- abts_wqeq->iocb_flag |= LPFC_IO_NVMET; ++ abts_wqeq->cmd_cmpl = lpfc_nvmet_unsol_fcp_abort_cmp; ++ abts_wqeq->cmd_flag |= LPFC_IO_NVMET; + if (!ctxp->hdwq) + ctxp->hdwq = &phba->sli4_hba.hdwq[abts_wqeq->hba_wqidx]; + +@@ -3614,9 +3620,8 @@ lpfc_nvme_unsol_ls_issue_abort(struct lpfc_hba *phba, + } + + spin_lock_irqsave(&phba->hbalock, flags); +- abts_wqeq->wqe_cmpl = lpfc_nvmet_xmt_ls_abort_cmp; +- abts_wqeq->iocb_cmpl = NULL; +- abts_wqeq->iocb_flag |= LPFC_IO_NVME_LS; ++ abts_wqeq->cmd_cmpl = lpfc_nvmet_xmt_ls_abort_cmp; ++ abts_wqeq->cmd_flag |= LPFC_IO_NVME_LS; + rc = lpfc_sli4_issue_wqe(phba, ctxp->hdwq, abts_wqeq); + spin_unlock_irqrestore(&phba->hbalock, flags); + if (rc == WQE_SUCCESS) { +diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c +index c6944b282e217..7da8e4c845df8 100644 +--- a/drivers/scsi/lpfc/lpfc_scsi.c ++++ b/drivers/scsi/lpfc/lpfc_scsi.c +@@ -362,7 +362,7 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc) + kfree(psb); + break; + } +- psb->cur_iocbq.iocb_flag |= LPFC_IO_FCP; ++ psb->cur_iocbq.cmd_flag |= LPFC_IO_FCP; + + psb->fcp_cmnd = psb->data; + psb->fcp_rsp = psb->data + sizeof(struct fcp_cmnd); +@@ -468,7 +468,7 @@ lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *vport) + spin_lock(&qp->abts_io_buf_list_lock); + list_for_each_entry_safe(psb, next_psb, + &qp->lpfc_abts_io_buf_list, list) { +- if (psb->cur_iocbq.iocb_flag & LPFC_IO_NVME) ++ if (psb->cur_iocbq.cmd_flag & LPFC_IO_NVME) + continue; + + if (psb->rdata && psb->rdata->pnode && +@@ -493,8 +493,8 @@ void + lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba, + struct sli4_wcqe_xri_aborted *axri, int idx) + { +- uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri); +- uint16_t rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri); ++ u16 xri = 0; ++ u16 rxid = 0; + struct lpfc_io_buf *psb, *next_psb; + struct lpfc_sli4_hdw_queue *qp; + unsigned long iflag = 0; +@@ -504,25 +504,39 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba, + int rrq_empty = 0; + struct lpfc_sli_ring *pring = phba->sli4_hba.els_wq->pring; + struct scsi_cmnd *cmd; ++ int offline = 0; + + if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP)) + return; +- ++ offline = pci_channel_offline(phba->pcidev); ++ if (!offline) { ++ xri = bf_get(lpfc_wcqe_xa_xri, axri); ++ rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri); ++ } + qp = &phba->sli4_hba.hdwq[idx]; + spin_lock_irqsave(&phba->hbalock, iflag); + spin_lock(&qp->abts_io_buf_list_lock); + list_for_each_entry_safe(psb, next_psb, + &qp->lpfc_abts_io_buf_list, list) { ++ if (offline) ++ xri = psb->cur_iocbq.sli4_xritag; + if (psb->cur_iocbq.sli4_xritag == xri) { + list_del_init(&psb->list); + psb->flags &= ~LPFC_SBUF_XBUSY; + psb->status = IOSTAT_SUCCESS; +- if (psb->cur_iocbq.iocb_flag & LPFC_IO_NVME) { ++ if (psb->cur_iocbq.cmd_flag & LPFC_IO_NVME) { + qp->abts_nvme_io_bufs--; + spin_unlock(&qp->abts_io_buf_list_lock); + spin_unlock_irqrestore(&phba->hbalock, iflag); +- lpfc_sli4_nvme_xri_aborted(phba, axri, psb); +- return; ++ if (!offline) { ++ lpfc_sli4_nvme_xri_aborted(phba, axri, ++ psb); ++ return; ++ } ++ lpfc_sli4_nvme_pci_offline_aborted(phba, psb); ++ spin_lock_irqsave(&phba->hbalock, iflag); ++ spin_lock(&qp->abts_io_buf_list_lock); ++ continue; + } + qp->abts_scsi_io_bufs--; + spin_unlock(&qp->abts_io_buf_list_lock); +@@ -534,13 +548,13 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba, + + rrq_empty = list_empty(&phba->active_rrq_list); + spin_unlock_irqrestore(&phba->hbalock, iflag); +- if (ndlp) { ++ if (ndlp && !offline) { + lpfc_set_rrq_active(phba, ndlp, + psb->cur_iocbq.sli4_lxritag, rxid, 1); + lpfc_sli4_abts_err_handler(phba, ndlp, axri); + } + +- if (phba->cfg_fcp_wait_abts_rsp) { ++ if (phba->cfg_fcp_wait_abts_rsp || offline) { + spin_lock_irqsave(&psb->buf_lock, iflag); + cmd = psb->pCmd; + psb->pCmd = NULL; +@@ -557,7 +571,7 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba, + * for command completion wake up the thread. + */ + spin_lock_irqsave(&psb->buf_lock, iflag); +- psb->cur_iocbq.iocb_flag &= ++ psb->cur_iocbq.cmd_flag &= + ~LPFC_DRIVER_ABORTED; + if (psb->waitq) + wake_up(psb->waitq); +@@ -567,25 +581,30 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba, + lpfc_release_scsi_buf_s4(phba, psb); + if (rrq_empty) + lpfc_worker_wake_up(phba); +- return; ++ if (!offline) ++ return; ++ spin_lock_irqsave(&phba->hbalock, iflag); ++ spin_lock(&qp->abts_io_buf_list_lock); ++ continue; + } + } + spin_unlock(&qp->abts_io_buf_list_lock); +- for (i = 1; i <= phba->sli.last_iotag; i++) { +- iocbq = phba->sli.iocbq_lookup[i]; +- +- if (!(iocbq->iocb_flag & LPFC_IO_FCP) || +- (iocbq->iocb_flag & LPFC_IO_LIBDFC)) +- continue; +- if (iocbq->sli4_xritag != xri) +- continue; +- psb = container_of(iocbq, struct lpfc_io_buf, cur_iocbq); +- psb->flags &= ~LPFC_SBUF_XBUSY; +- spin_unlock_irqrestore(&phba->hbalock, iflag); +- if (!list_empty(&pring->txq)) +- lpfc_worker_wake_up(phba); +- return; ++ if (!offline) { ++ for (i = 1; i <= phba->sli.last_iotag; i++) { ++ iocbq = phba->sli.iocbq_lookup[i]; + ++ if (!(iocbq->cmd_flag & LPFC_IO_FCP) || ++ (iocbq->cmd_flag & LPFC_IO_LIBDFC)) ++ continue; ++ if (iocbq->sli4_xritag != xri) ++ continue; ++ psb = container_of(iocbq, struct lpfc_io_buf, cur_iocbq); ++ psb->flags &= ~LPFC_SBUF_XBUSY; ++ spin_unlock_irqrestore(&phba->hbalock, iflag); ++ if (!list_empty(&pring->txq)) ++ lpfc_worker_wake_up(phba); ++ return; ++ } + } + spin_unlock_irqrestore(&phba->hbalock, iflag); + } +@@ -676,7 +695,7 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, + /* Setup key fields in buffer that may have been changed + * if other protocols used this buffer. + */ +- lpfc_cmd->cur_iocbq.iocb_flag = LPFC_IO_FCP; ++ lpfc_cmd->cur_iocbq.cmd_flag = LPFC_IO_FCP; + lpfc_cmd->prot_seg_cnt = 0; + lpfc_cmd->seg_cnt = 0; + lpfc_cmd->timeout = 0; +@@ -764,7 +783,7 @@ lpfc_release_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *psb) + + spin_lock_irqsave(&phba->scsi_buf_list_put_lock, iflag); + psb->pCmd = NULL; +- psb->cur_iocbq.iocb_flag = LPFC_IO_FCP; ++ psb->cur_iocbq.cmd_flag = LPFC_IO_FCP; + list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list_put); + spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, iflag); + } +@@ -912,7 +931,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) + physaddr = sg_dma_address(sgel); + if (phba->sli_rev == 3 && + !(phba->sli3_options & LPFC_SLI3_BG_ENABLED) && +- !(iocbq->iocb_flag & DSS_SECURITY_OP) && ++ !(iocbq->cmd_flag & DSS_SECURITY_OP) && + nseg <= LPFC_EXT_DATA_BDE_COUNT) { + data_bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64; + data_bde->tus.f.bdeSize = sg_dma_len(sgel); +@@ -940,7 +959,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) + */ + if (phba->sli_rev == 3 && + !(phba->sli3_options & LPFC_SLI3_BG_ENABLED) && +- !(iocbq->iocb_flag & DSS_SECURITY_OP)) { ++ !(iocbq->cmd_flag & DSS_SECURITY_OP)) { + if (num_bde > LPFC_EXT_DATA_BDE_COUNT) { + /* + * The extended IOCB format can only fit 3 BDE or a BPL. +@@ -2923,154 +2942,58 @@ out: + * -1 - Internal error (bad profile, ...etc) + */ + static int +-lpfc_sli4_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, +- struct lpfc_wcqe_complete *wcqe) ++lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, ++ struct lpfc_iocbq *pIocbOut) + { + struct scsi_cmnd *cmd = lpfc_cmd->pCmd; ++ struct sli3_bg_fields *bgf; + int ret = 0; +- u32 status = bf_get(lpfc_wcqe_c_status, wcqe); ++ struct lpfc_wcqe_complete *wcqe; ++ u32 status; + u32 bghm = 0; + u32 bgstat = 0; + u64 failing_sector = 0; + +- if (status == CQE_STATUS_DI_ERROR) { +- if (bf_get(lpfc_wcqe_c_bg_ge, wcqe)) /* Guard Check failed */ +- bgstat |= BGS_GUARD_ERR_MASK; +- if (bf_get(lpfc_wcqe_c_bg_ae, wcqe)) /* AppTag Check failed */ +- bgstat |= BGS_APPTAG_ERR_MASK; +- if (bf_get(lpfc_wcqe_c_bg_re, wcqe)) /* RefTag Check failed */ +- bgstat |= BGS_REFTAG_ERR_MASK; +- +- /* Check to see if there was any good data before the error */ +- if (bf_get(lpfc_wcqe_c_bg_tdpv, wcqe)) { +- bgstat |= BGS_HI_WATER_MARK_PRESENT_MASK; +- bghm = wcqe->total_data_placed; +- } +- +- /* +- * Set ALL the error bits to indicate we don't know what +- * type of error it is. +- */ +- if (!bgstat) +- bgstat |= (BGS_REFTAG_ERR_MASK | BGS_APPTAG_ERR_MASK | +- BGS_GUARD_ERR_MASK); +- } +- +- if (lpfc_bgs_get_guard_err(bgstat)) { +- ret = 1; +- +- scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x1); +- set_host_byte(cmd, DID_ABORT); +- phba->bg_guard_err_cnt++; +- lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, +- "9059 BLKGRD: Guard Tag error in cmd" +- " 0x%x lba 0x%llx blk cnt 0x%x " +- "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], +- (unsigned long long)scsi_get_lba(cmd), +- scsi_logical_block_count(cmd), bgstat, bghm); +- } +- +- if (lpfc_bgs_get_reftag_err(bgstat)) { +- ret = 1; +- +- scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x3); +- set_host_byte(cmd, DID_ABORT); +- +- phba->bg_reftag_err_cnt++; +- lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, +- "9060 BLKGRD: Ref Tag error in cmd" +- " 0x%x lba 0x%llx blk cnt 0x%x " +- "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], +- (unsigned long long)scsi_get_lba(cmd), +- scsi_logical_block_count(cmd), bgstat, bghm); +- } ++ if (phba->sli_rev == LPFC_SLI_REV4) { ++ wcqe = &pIocbOut->wcqe_cmpl; ++ status = bf_get(lpfc_wcqe_c_status, wcqe); + +- if (lpfc_bgs_get_apptag_err(bgstat)) { +- ret = 1; ++ if (status == CQE_STATUS_DI_ERROR) { ++ /* Guard Check failed */ ++ if (bf_get(lpfc_wcqe_c_bg_ge, wcqe)) ++ bgstat |= BGS_GUARD_ERR_MASK; + +- scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x2); +- set_host_byte(cmd, DID_ABORT); ++ /* AppTag Check failed */ ++ if (bf_get(lpfc_wcqe_c_bg_ae, wcqe)) ++ bgstat |= BGS_APPTAG_ERR_MASK; + +- phba->bg_apptag_err_cnt++; +- lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, +- "9062 BLKGRD: App Tag error in cmd" +- " 0x%x lba 0x%llx blk cnt 0x%x " +- "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], +- (unsigned long long)scsi_get_lba(cmd), +- scsi_logical_block_count(cmd), bgstat, bghm); +- } ++ /* RefTag Check failed */ ++ if (bf_get(lpfc_wcqe_c_bg_re, wcqe)) ++ bgstat |= BGS_REFTAG_ERR_MASK; + +- if (lpfc_bgs_get_hi_water_mark_present(bgstat)) { +- /* +- * setup sense data descriptor 0 per SPC-4 as an information +- * field, and put the failing LBA in it. +- * This code assumes there was also a guard/app/ref tag error +- * indication. +- */ +- cmd->sense_buffer[7] = 0xc; /* Additional sense length */ +- cmd->sense_buffer[8] = 0; /* Information descriptor type */ +- cmd->sense_buffer[9] = 0xa; /* Additional descriptor length */ +- cmd->sense_buffer[10] = 0x80; /* Validity bit */ ++ /* Check to see if there was any good data before the ++ * error ++ */ ++ if (bf_get(lpfc_wcqe_c_bg_tdpv, wcqe)) { ++ bgstat |= BGS_HI_WATER_MARK_PRESENT_MASK; ++ bghm = wcqe->total_data_placed; ++ } + +- /* bghm is a "on the wire" FC frame based count */ +- switch (scsi_get_prot_op(cmd)) { +- case SCSI_PROT_READ_INSERT: +- case SCSI_PROT_WRITE_STRIP: +- bghm /= cmd->device->sector_size; +- break; +- case SCSI_PROT_READ_STRIP: +- case SCSI_PROT_WRITE_INSERT: +- case SCSI_PROT_READ_PASS: +- case SCSI_PROT_WRITE_PASS: +- bghm /= (cmd->device->sector_size + +- sizeof(struct scsi_dif_tuple)); +- break; ++ /* ++ * Set ALL the error bits to indicate we don't know what ++ * type of error it is. ++ */ ++ if (!bgstat) ++ bgstat |= (BGS_REFTAG_ERR_MASK | ++ BGS_APPTAG_ERR_MASK | ++ BGS_GUARD_ERR_MASK); + } + +- failing_sector = scsi_get_lba(cmd); +- failing_sector += bghm; +- +- /* Descriptor Information */ +- put_unaligned_be64(failing_sector, &cmd->sense_buffer[12]); +- } +- +- if (!ret) { +- /* No error was reported - problem in FW? */ +- lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, +- "9068 BLKGRD: Unknown error in cmd" +- " 0x%x lba 0x%llx blk cnt 0x%x " +- "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], +- (unsigned long long)scsi_get_lba(cmd), +- scsi_logical_block_count(cmd), bgstat, bghm); +- +- /* Calculate what type of error it was */ +- lpfc_calc_bg_err(phba, lpfc_cmd); ++ } else { ++ bgf = &pIocbOut->iocb.unsli3.sli3_bg; ++ bghm = bgf->bghm; ++ bgstat = bgf->bgstat; + } +- return ret; +-} +- +-/* +- * This function checks for BlockGuard errors detected by +- * the HBA. In case of errors, the ASC/ASCQ fields in the +- * sense buffer will be set accordingly, paired with +- * ILLEGAL_REQUEST to signal to the kernel that the HBA +- * detected corruption. +- * +- * Returns: +- * 0 - No error found +- * 1 - BlockGuard error found +- * -1 - Internal error (bad profile, ...etc) +- */ +-static int +-lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, +- struct lpfc_iocbq *pIocbOut) +-{ +- struct scsi_cmnd *cmd = lpfc_cmd->pCmd; +- struct sli3_bg_fields *bgf = &pIocbOut->iocb.unsli3.sli3_bg; +- int ret = 0; +- uint32_t bghm = bgf->bghm; +- uint32_t bgstat = bgf->bgstat; +- uint64_t failing_sector = 0; + + if (lpfc_bgs_get_invalid_prof(bgstat)) { + cmd->result = DID_ERROR << 16; +@@ -3098,7 +3021,6 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, + + if (lpfc_bgs_get_guard_err(bgstat)) { + ret = 1; +- + scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x1); + set_host_byte(cmd, DID_ABORT); + phba->bg_guard_err_cnt++; +@@ -3112,10 +3034,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, + + if (lpfc_bgs_get_reftag_err(bgstat)) { + ret = 1; +- + scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x3); + set_host_byte(cmd, DID_ABORT); +- + phba->bg_reftag_err_cnt++; + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, + "9056 BLKGRD: Ref Tag error in cmd " +@@ -3127,10 +3047,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, + + if (lpfc_bgs_get_apptag_err(bgstat)) { + ret = 1; +- + scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x2); + set_host_byte(cmd, DID_ABORT); +- + phba->bg_apptag_err_cnt++; + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, + "9061 BLKGRD: App Tag error in cmd " +@@ -3415,7 +3333,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) + */ + if ((phba->cfg_fof) && ((struct lpfc_device_data *) + scsi_cmnd->device->hostdata)->oas_enabled) { +- lpfc_cmd->cur_iocbq.iocb_flag |= (LPFC_IO_OAS | LPFC_IO_FOF); ++ lpfc_cmd->cur_iocbq.cmd_flag |= (LPFC_IO_OAS | LPFC_IO_FOF); + lpfc_cmd->cur_iocbq.priority = ((struct lpfc_device_data *) + scsi_cmnd->device->hostdata)->priority; + +@@ -3572,15 +3490,15 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, + switch (scsi_get_prot_op(scsi_cmnd)) { + case SCSI_PROT_WRITE_STRIP: + case SCSI_PROT_READ_STRIP: +- lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF_STRIP; ++ lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_DIF_STRIP; + break; + case SCSI_PROT_WRITE_INSERT: + case SCSI_PROT_READ_INSERT: +- lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF_INSERT; ++ lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_DIF_INSERT; + break; + case SCSI_PROT_WRITE_PASS: + case SCSI_PROT_READ_PASS: +- lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF_PASS; ++ lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_DIF_PASS; + break; + } + +@@ -3611,7 +3529,7 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, + */ + if ((phba->cfg_fof) && ((struct lpfc_device_data *) + scsi_cmnd->device->hostdata)->oas_enabled) { +- lpfc_cmd->cur_iocbq.iocb_flag |= (LPFC_IO_OAS | LPFC_IO_FOF); ++ lpfc_cmd->cur_iocbq.cmd_flag |= (LPFC_IO_OAS | LPFC_IO_FOF); + + /* Word 10 */ + bf_set(wqe_oas, &wqe->generic.wqe_com, 1); +@@ -3621,14 +3539,14 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, + } + + /* Word 7. DIF Flags */ +- if (lpfc_cmd->cur_iocbq.iocb_flag & LPFC_IO_DIF_PASS) ++ if (lpfc_cmd->cur_iocbq.cmd_flag & LPFC_IO_DIF_PASS) + bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_PASSTHRU); +- else if (lpfc_cmd->cur_iocbq.iocb_flag & LPFC_IO_DIF_STRIP) ++ else if (lpfc_cmd->cur_iocbq.cmd_flag & LPFC_IO_DIF_STRIP) + bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_STRIP); +- else if (lpfc_cmd->cur_iocbq.iocb_flag & LPFC_IO_DIF_INSERT) ++ else if (lpfc_cmd->cur_iocbq.cmd_flag & LPFC_IO_DIF_INSERT) + bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_INSERT); + +- lpfc_cmd->cur_iocbq.iocb_flag &= ~(LPFC_IO_DIF_PASS | ++ lpfc_cmd->cur_iocbq.cmd_flag &= ~(LPFC_IO_DIF_PASS | + LPFC_IO_DIF_STRIP | LPFC_IO_DIF_INSERT); + + return 0; +@@ -4153,7 +4071,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, + * lpfc_fcp_io_cmd_wqe_cmpl - Complete a FCP IO + * @phba: The hba for which this call is being executed. + * @pwqeIn: The command WQE for the scsi cmnd. +- * @wcqe: Pointer to driver response CQE object. ++ * @pwqeOut: Pointer to driver response WQE object. + * + * This routine assigns scsi command result by looking into response WQE + * status field appropriately. This routine handles QUEUE FULL condition as +@@ -4161,10 +4079,11 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, + **/ + static void + lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, +- struct lpfc_wcqe_complete *wcqe) ++ struct lpfc_iocbq *pwqeOut) + { + struct lpfc_io_buf *lpfc_cmd = + (struct lpfc_io_buf *)pwqeIn->context1; ++ struct lpfc_wcqe_complete *wcqe = &pwqeOut->wcqe_cmpl; + struct lpfc_vport *vport = pwqeIn->vport; + struct lpfc_rport_data *rdata; + struct lpfc_nodelist *ndlp; +@@ -4174,7 +4093,6 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, + struct Scsi_Host *shost; + u32 logit = LOG_FCP; + u32 status, idx; +- unsigned long iflags = 0; + u32 lat; + u8 wait_xb_clr = 0; + +@@ -4189,30 +4107,16 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, + rdata = lpfc_cmd->rdata; + ndlp = rdata->pnode; + +- if (bf_get(lpfc_wcqe_c_xb, wcqe)) { +- /* TOREMOVE - currently this flag is checked during +- * the release of lpfc_iocbq. Remove once we move +- * to lpfc_wqe_job construct. +- * +- * This needs to be done outside buf_lock +- */ +- spin_lock_irqsave(&phba->hbalock, iflags); +- lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_EXCHANGE_BUSY; +- spin_unlock_irqrestore(&phba->hbalock, iflags); +- } +- +- /* Guard against abort handler being called at same time */ +- spin_lock(&lpfc_cmd->buf_lock); +- + /* Sanity check on return of outstanding command */ + cmd = lpfc_cmd->pCmd; + if (!cmd) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "9042 I/O completion: Not an active IO\n"); +- spin_unlock(&lpfc_cmd->buf_lock); + lpfc_release_scsi_buf(phba, lpfc_cmd); + return; + } ++ /* Guard against abort handler being called at same time */ ++ spin_lock(&lpfc_cmd->buf_lock); + idx = lpfc_cmd->cur_iocbq.hba_wqidx; + if (phba->sli4_hba.hdwq) + phba->sli4_hba.hdwq[idx].scsi_cstat.io_cmpls++; +@@ -4386,12 +4290,14 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, + * This is a response for a BG enabled + * cmd. Parse BG error + */ +- lpfc_sli4_parse_bg_err(phba, lpfc_cmd, +- wcqe); ++ lpfc_parse_bg_err(phba, lpfc_cmd, pwqeOut); + break; ++ } else { ++ lpfc_printf_vlog(vport, KERN_WARNING, ++ LOG_BG, ++ "9040 non-zero BGSTAT " ++ "on unprotected cmd\n"); + } +- lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, +- "9040 non-zero BGSTAT on unprotected cmd\n"); + } + lpfc_printf_vlog(vport, KERN_WARNING, logit, + "9036 Local Reject FCP cmd x%x failed" +@@ -4488,7 +4394,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, + * wake up the thread. + */ + spin_lock(&lpfc_cmd->buf_lock); +- lpfc_cmd->cur_iocbq.iocb_flag &= ~LPFC_DRIVER_ABORTED; ++ lpfc_cmd->cur_iocbq.cmd_flag &= ~LPFC_DRIVER_ABORTED; + if (lpfc_cmd->waitq) + wake_up(lpfc_cmd->waitq); + spin_unlock(&lpfc_cmd->buf_lock); +@@ -4548,7 +4454,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, + lpfc_cmd->status = pIocbOut->iocb.ulpStatus; + /* pick up SLI4 exchange busy status from HBA */ + lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY; +- if (pIocbOut->iocb_flag & LPFC_EXCHANGE_BUSY) ++ if (pIocbOut->cmd_flag & LPFC_EXCHANGE_BUSY) + lpfc_cmd->flags |= LPFC_SBUF_XBUSY; + + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS +@@ -4757,7 +4663,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, + * wake up the thread. + */ + spin_lock(&lpfc_cmd->buf_lock); +- lpfc_cmd->cur_iocbq.iocb_flag &= ~LPFC_DRIVER_ABORTED; ++ lpfc_cmd->cur_iocbq.cmd_flag &= ~LPFC_DRIVER_ABORTED; + if (lpfc_cmd->waitq) + wake_up(lpfc_cmd->waitq); + spin_unlock(&lpfc_cmd->buf_lock); +@@ -4835,8 +4741,8 @@ static int lpfc_scsi_prep_cmnd_buf_s3(struct lpfc_vport *vport, + + piocbq->iocb.ulpClass = (pnode->nlp_fcp_info & 0x0f); + piocbq->context1 = lpfc_cmd; +- if (!piocbq->iocb_cmpl) +- piocbq->iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl; ++ if (!piocbq->cmd_cmpl) ++ piocbq->cmd_cmpl = lpfc_scsi_cmd_iocb_cmpl; + piocbq->iocb.ulpTimeout = tmo; + piocbq->vport = vport; + return 0; +@@ -4949,7 +4855,7 @@ static int lpfc_scsi_prep_cmnd_buf_s4(struct lpfc_vport *vport, + pwqeq->vport = vport; + pwqeq->context1 = lpfc_cmd; + pwqeq->hba_wqidx = lpfc_cmd->hdwq_no; +- pwqeq->wqe_cmpl = lpfc_fcp_io_cmd_wqe_cmpl; ++ pwqeq->cmd_cmpl = lpfc_fcp_io_cmd_wqe_cmpl; + + return 0; + } +@@ -4996,7 +4902,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, + } + + /** +- * lpfc_scsi_prep_task_mgmt_cmd - Convert SLI3 scsi TM cmd to FCP info unit ++ * lpfc_scsi_prep_task_mgmt_cmd_s3 - Convert SLI3 scsi TM cmd to FCP info unit + * @vport: The virtual port for which this call is being executed. + * @lpfc_cmd: Pointer to lpfc_io_buf data structure. + * @lun: Logical unit number. +@@ -5010,10 +4916,9 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, + * 1 - Success + **/ + static int +-lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, +- struct lpfc_io_buf *lpfc_cmd, +- uint64_t lun, +- uint8_t task_mgmt_cmd) ++lpfc_scsi_prep_task_mgmt_cmd_s3(struct lpfc_vport *vport, ++ struct lpfc_io_buf *lpfc_cmd, ++ u64 lun, u8 task_mgmt_cmd) + { + struct lpfc_iocbq *piocbq; + IOCB_t *piocb; +@@ -5034,15 +4939,10 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, + memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd)); + int_to_scsilun(lun, &fcp_cmnd->fcp_lun); + fcp_cmnd->fcpCntl2 = task_mgmt_cmd; +- if (vport->phba->sli_rev == 3 && +- !(vport->phba->sli3_options & LPFC_SLI3_BG_ENABLED)) ++ if (!(vport->phba->sli3_options & LPFC_SLI3_BG_ENABLED)) + lpfc_fcpcmd_to_iocb(piocb->unsli3.fcp_ext.icd, fcp_cmnd); + piocb->ulpCommand = CMD_FCP_ICMND64_CR; + piocb->ulpContext = ndlp->nlp_rpi; +- if (vport->phba->sli_rev == LPFC_SLI_REV4) { +- piocb->ulpContext = +- vport->phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; +- } + piocb->ulpFCP2Rcvy = (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) ? 1 : 0; + piocb->ulpClass = (ndlp->nlp_fcp_info & 0x0f); + piocb->ulpPU = 0; +@@ -5058,8 +4958,79 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, + } else + piocb->ulpTimeout = lpfc_cmd->timeout; + +- if (vport->phba->sli_rev == LPFC_SLI_REV4) +- lpfc_sli4_set_rsp_sgl_last(vport->phba, lpfc_cmd); ++ return 1; ++} ++ ++/** ++ * lpfc_scsi_prep_task_mgmt_cmd_s4 - Convert SLI4 scsi TM cmd to FCP info unit ++ * @vport: The virtual port for which this call is being executed. ++ * @lpfc_cmd: Pointer to lpfc_io_buf data structure. ++ * @lun: Logical unit number. ++ * @task_mgmt_cmd: SCSI task management command. ++ * ++ * This routine creates FCP information unit corresponding to @task_mgmt_cmd ++ * for device with SLI-4 interface spec. ++ * ++ * Return codes: ++ * 0 - Error ++ * 1 - Success ++ **/ ++static int ++lpfc_scsi_prep_task_mgmt_cmd_s4(struct lpfc_vport *vport, ++ struct lpfc_io_buf *lpfc_cmd, ++ u64 lun, u8 task_mgmt_cmd) ++{ ++ struct lpfc_iocbq *pwqeq = &lpfc_cmd->cur_iocbq; ++ union lpfc_wqe128 *wqe = &pwqeq->wqe; ++ struct fcp_cmnd *fcp_cmnd; ++ struct lpfc_rport_data *rdata = lpfc_cmd->rdata; ++ struct lpfc_nodelist *ndlp = rdata->pnode; ++ ++ if (!ndlp || ndlp->nlp_state != NLP_STE_MAPPED_NODE) ++ return 0; ++ ++ pwqeq->vport = vport; ++ /* Initialize 64 bytes only */ ++ memset(wqe, 0, sizeof(union lpfc_wqe128)); ++ ++ /* From the icmnd template, initialize words 4 - 11 */ ++ memcpy(&wqe->words[4], &lpfc_icmnd_cmd_template.words[4], ++ sizeof(uint32_t) * 8); ++ ++ fcp_cmnd = lpfc_cmd->fcp_cmnd; ++ /* Clear out any old data in the FCP command area */ ++ memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd)); ++ int_to_scsilun(lun, &fcp_cmnd->fcp_lun); ++ fcp_cmnd->fcpCntl3 = 0; ++ fcp_cmnd->fcpCntl2 = task_mgmt_cmd; ++ ++ bf_set(payload_offset_len, &wqe->fcp_icmd, ++ sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp)); ++ bf_set(cmd_buff_len, &wqe->fcp_icmd, 0); ++ bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, /* ulpContext */ ++ vport->phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); ++ bf_set(wqe_erp, &wqe->fcp_icmd.wqe_com, ++ ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) ? 1 : 0)); ++ bf_set(wqe_class, &wqe->fcp_icmd.wqe_com, ++ (ndlp->nlp_fcp_info & 0x0f)); ++ ++ /* ulpTimeout is only one byte */ ++ if (lpfc_cmd->timeout > 0xff) { ++ /* ++ * Do not timeout the command at the firmware level. ++ * The driver will provide the timeout mechanism. ++ */ ++ bf_set(wqe_tmo, &wqe->fcp_icmd.wqe_com, 0); ++ } else { ++ bf_set(wqe_tmo, &wqe->fcp_icmd.wqe_com, lpfc_cmd->timeout); ++ } ++ ++ lpfc_prep_embed_io(vport->phba, lpfc_cmd); ++ bf_set(wqe_xri_tag, &wqe->generic.wqe_com, pwqeq->sli4_xritag); ++ wqe->generic.wqe_com.abort_tag = pwqeq->iotag; ++ bf_set(wqe_reqtag, &wqe->generic.wqe_com, pwqeq->iotag); ++ ++ lpfc_sli4_set_rsp_sgl_last(vport->phba, lpfc_cmd); + + return 1; + } +@@ -5086,6 +5057,8 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) + phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s3; + phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s3; + phba->lpfc_scsi_prep_cmnd_buf = lpfc_scsi_prep_cmnd_buf_s3; ++ phba->lpfc_scsi_prep_task_mgmt_cmd = ++ lpfc_scsi_prep_task_mgmt_cmd_s3; + break; + case LPFC_PCI_DEV_OC: + phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s4; +@@ -5093,6 +5066,8 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) + phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s4; + phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s4; + phba->lpfc_scsi_prep_cmnd_buf = lpfc_scsi_prep_cmnd_buf_s4; ++ phba->lpfc_scsi_prep_task_mgmt_cmd = ++ lpfc_scsi_prep_task_mgmt_cmd_s4; + break; + default: + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, +@@ -5571,6 +5546,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) + { + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; ++ struct lpfc_iocbq *cur_iocbq = NULL; + struct lpfc_rport_data *rdata; + struct lpfc_nodelist *ndlp; + struct lpfc_io_buf *lpfc_cmd; +@@ -5664,6 +5640,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) + } + lpfc_cmd->rx_cmd_start = start; + ++ cur_iocbq = &lpfc_cmd->cur_iocbq; + /* + * Store the midlayer's command structure for the completion phase + * and complete the command initialization. +@@ -5671,7 +5648,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) + lpfc_cmd->pCmd = cmnd; + lpfc_cmd->rdata = rdata; + lpfc_cmd->ndlp = ndlp; +- lpfc_cmd->cur_iocbq.iocb_cmpl = NULL; ++ cur_iocbq->cmd_cmpl = NULL; + cmnd->host_scribble = (unsigned char *)lpfc_cmd; + + err = lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp); +@@ -5713,7 +5690,6 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) + goto out_host_busy_free_buf; + } + +- + /* check the necessary and sufficient condition to support VMID */ + if (lpfc_is_vmid_enabled(phba) && + (ndlp->vmid_support || +@@ -5726,20 +5702,18 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) + if (uuid) { + err = lpfc_vmid_get_appid(vport, uuid, cmnd, + (union lpfc_vmid_io_tag *) +- &lpfc_cmd->cur_iocbq.vmid_tag); ++ &cur_iocbq->vmid_tag); + if (!err) +- lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_VMID; ++ cur_iocbq->cmd_flag |= LPFC_IO_VMID; + } + } + +- atomic_inc(&ndlp->cmd_pending); + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS + if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO)) + this_cpu_inc(phba->sli4_hba.c_stat->xmt_io); + #endif + /* Issue I/O to adapter */ +- err = lpfc_sli_issue_fcp_io(phba, LPFC_FCP_RING, +- &lpfc_cmd->cur_iocbq, ++ err = lpfc_sli_issue_fcp_io(phba, LPFC_FCP_RING, cur_iocbq, + SLI_IOCB_RET_IOCB); + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS + if (start) { +@@ -5752,25 +5726,25 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) + #endif + if (err) { + lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, +- "3376 FCP could not issue IOCB err %x " +- "FCP cmd x%x <%d/%llu> " +- "sid: x%x did: x%x oxid: x%x " +- "Data: x%x x%x x%x x%x\n", +- err, cmnd->cmnd[0], +- cmnd->device ? cmnd->device->id : 0xffff, +- cmnd->device ? cmnd->device->lun : (u64)-1, +- vport->fc_myDID, ndlp->nlp_DID, +- phba->sli_rev == LPFC_SLI_REV4 ? +- lpfc_cmd->cur_iocbq.sli4_xritag : 0xffff, +- phba->sli_rev == LPFC_SLI_REV4 ? +- phba->sli4_hba.rpi_ids[ndlp->nlp_rpi] : +- lpfc_cmd->cur_iocbq.iocb.ulpContext, +- lpfc_cmd->cur_iocbq.iotag, +- phba->sli_rev == LPFC_SLI_REV4 ? +- bf_get(wqe_tmo, +- &lpfc_cmd->cur_iocbq.wqe.generic.wqe_com) : +- lpfc_cmd->cur_iocbq.iocb.ulpTimeout, +- (uint32_t)(scsi_cmd_to_rq(cmnd)->timeout / 1000)); ++ "3376 FCP could not issue iocb err %x " ++ "FCP cmd x%x <%d/%llu> " ++ "sid: x%x did: x%x oxid: x%x " ++ "Data: x%x x%x x%x x%x\n", ++ err, cmnd->cmnd[0], ++ cmnd->device ? cmnd->device->id : 0xffff, ++ cmnd->device ? cmnd->device->lun : (u64)-1, ++ vport->fc_myDID, ndlp->nlp_DID, ++ phba->sli_rev == LPFC_SLI_REV4 ? ++ cur_iocbq->sli4_xritag : 0xffff, ++ phba->sli_rev == LPFC_SLI_REV4 ? ++ phba->sli4_hba.rpi_ids[ndlp->nlp_rpi] : ++ cur_iocbq->iocb.ulpContext, ++ cur_iocbq->iotag, ++ phba->sli_rev == LPFC_SLI_REV4 ? ++ bf_get(wqe_tmo, ++ &cur_iocbq->wqe.generic.wqe_com) : ++ cur_iocbq->iocb.ulpTimeout, ++ (uint32_t)(scsi_cmd_to_rq(cmnd)->timeout / 1000)); + + goto out_host_busy_free_buf; + } +@@ -5916,7 +5890,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) + spin_lock(&pring_s4->ring_lock); + } + /* the command is in process of being cancelled */ +- if (!(iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ)) { ++ if (!(iocb->cmd_flag & LPFC_IO_ON_TXCMPLQ)) { + lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, + "3169 SCSI Layer abort requested I/O has been " + "cancelled by LLD.\n"); +@@ -5939,7 +5913,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) + BUG_ON(iocb->context1 != lpfc_cmd); + + /* abort issued in recovery is still in progress */ +- if (iocb->iocb_flag & LPFC_DRIVER_ABORTED) { ++ if (iocb->cmd_flag & LPFC_DRIVER_ABORTED) { + lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, + "3389 SCSI Layer I/O Abort Request is pending\n"); + if (phba->sli_rev == LPFC_SLI_REV4) +@@ -5980,7 +5954,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) + + wait_for_cmpl: + /* +- * iocb_flag is set to LPFC_DRIVER_ABORTED before we wait ++ * cmd_flag is set to LPFC_DRIVER_ABORTED before we wait + * for abort to complete. + */ + wait_event_timeout(waitq, +@@ -6147,7 +6121,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd, + return FAILED; + pnode = rdata->pnode; + +- lpfc_cmd = lpfc_get_scsi_buf(phba, pnode, NULL); ++ lpfc_cmd = lpfc_get_scsi_buf(phba, rdata->pnode, NULL); + if (lpfc_cmd == NULL) + return FAILED; + lpfc_cmd->timeout = phba->cfg_task_mgmt_tmo; +@@ -6155,8 +6129,8 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd, + lpfc_cmd->pCmd = cmnd; + lpfc_cmd->ndlp = pnode; + +- status = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun_id, +- task_mgmt_cmd); ++ status = phba->lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun_id, ++ task_mgmt_cmd); + if (!status) { + lpfc_release_scsi_buf(phba, lpfc_cmd); + return FAILED; +@@ -6168,38 +6142,41 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd, + lpfc_release_scsi_buf(phba, lpfc_cmd); + return FAILED; + } +- iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl; ++ iocbq->cmd_cmpl = lpfc_tskmgmt_def_cmpl; ++ iocbq->vport = vport; + + lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, + "0702 Issue %s to TGT %d LUN %llu " + "rpi x%x nlp_flag x%x Data: x%x x%x\n", + lpfc_taskmgmt_name(task_mgmt_cmd), tgt_id, lun_id, + pnode->nlp_rpi, pnode->nlp_flag, iocbq->sli4_xritag, +- iocbq->iocb_flag); ++ iocbq->cmd_flag); + + status = lpfc_sli_issue_iocb_wait(phba, LPFC_FCP_RING, + iocbq, iocbqrsp, lpfc_cmd->timeout); + if ((status != IOCB_SUCCESS) || +- (iocbqrsp->iocb.ulpStatus != IOSTAT_SUCCESS)) { ++ (get_job_ulpstatus(phba, iocbqrsp) != IOSTAT_SUCCESS)) { + if (status != IOCB_SUCCESS || +- iocbqrsp->iocb.ulpStatus != IOSTAT_FCP_RSP_ERROR) ++ get_job_ulpstatus(phba, iocbqrsp) != IOSTAT_FCP_RSP_ERROR) + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "0727 TMF %s to TGT %d LUN %llu " +- "failed (%d, %d) iocb_flag x%x\n", ++ "failed (%d, %d) cmd_flag x%x\n", + lpfc_taskmgmt_name(task_mgmt_cmd), + tgt_id, lun_id, +- iocbqrsp->iocb.ulpStatus, +- iocbqrsp->iocb.un.ulpWord[4], +- iocbq->iocb_flag); ++ get_job_ulpstatus(phba, iocbqrsp), ++ get_job_word4(phba, iocbqrsp), ++ iocbq->cmd_flag); + /* if ulpStatus != IOCB_SUCCESS, then status == IOCB_SUCCESS */ + if (status == IOCB_SUCCESS) { +- if (iocbqrsp->iocb.ulpStatus == IOSTAT_FCP_RSP_ERROR) ++ if (get_job_ulpstatus(phba, iocbqrsp) == ++ IOSTAT_FCP_RSP_ERROR) + /* Something in the FCP_RSP was invalid. + * Check conditions */ + ret = lpfc_check_fcp_rsp(vport, lpfc_cmd); + else + ret = FAILED; +- } else if (status == IOCB_TIMEDOUT) { ++ } else if ((status == IOCB_TIMEDOUT) || ++ (status == IOCB_ABORTED)) { + ret = TIMEOUT_ERROR; + } else { + ret = FAILED; +@@ -6209,7 +6186,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd, + + lpfc_sli_release_iocbq(phba, iocbqrsp); + +- if (ret != TIMEOUT_ERROR) ++ if (status != IOCB_TIMEDOUT) + lpfc_release_scsi_buf(phba, lpfc_cmd); + + return ret; +diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c +index d8d26cde70b65..fb69416c9623b 100644 +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -70,8 +70,9 @@ static int lpfc_sli_issue_mbox_s4(struct lpfc_hba *, LPFC_MBOXQ_t *, + uint32_t); + static int lpfc_sli4_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *, + uint8_t *, uint32_t *); +-static struct lpfc_iocbq *lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *, +- struct lpfc_iocbq *); ++static struct lpfc_iocbq * ++lpfc_sli4_els_preprocess_rspiocbq(struct lpfc_hba *phba, ++ struct lpfc_iocbq *rspiocbq); + static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *, + struct hbq_dmabuf *); + static void lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport, +@@ -89,6 +90,9 @@ static struct lpfc_cqe *lpfc_sli4_cq_get(struct lpfc_queue *q); + static void __lpfc_sli4_consume_cqe(struct lpfc_hba *phba, + struct lpfc_queue *cq, + struct lpfc_cqe *cqe); ++static uint16_t lpfc_wqe_bpl2sgl(struct lpfc_hba *phba, ++ struct lpfc_iocbq *pwqeq, ++ struct lpfc_sglq *sglq); + + union lpfc_wqe128 lpfc_iread_cmd_template; + union lpfc_wqe128 lpfc_iwrite_cmd_template; +@@ -1254,21 +1258,21 @@ __lpfc_sli_get_els_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq) + struct lpfc_sli_ring *pring = NULL; + int found = 0; + +- if (piocbq->iocb_flag & LPFC_IO_NVME_LS) ++ if (piocbq->cmd_flag & LPFC_IO_NVME_LS) + pring = phba->sli4_hba.nvmels_wq->pring; + else + pring = lpfc_phba_elsring(phba); + + lockdep_assert_held(&pring->ring_lock); + +- if (piocbq->iocb_flag & LPFC_IO_FCP) { ++ if (piocbq->cmd_flag & LPFC_IO_FCP) { + lpfc_cmd = (struct lpfc_io_buf *) piocbq->context1; + ndlp = lpfc_cmd->rdata->pnode; + } else if ((piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) && +- !(piocbq->iocb_flag & LPFC_IO_LIBDFC)) { ++ !(piocbq->cmd_flag & LPFC_IO_LIBDFC)) { + ndlp = piocbq->context_un.ndlp; +- } else if (piocbq->iocb_flag & LPFC_IO_LIBDFC) { +- if (piocbq->iocb_flag & LPFC_IO_LOOPBACK) ++ } else if (piocbq->cmd_flag & LPFC_IO_LIBDFC) { ++ if (piocbq->cmd_flag & LPFC_IO_LOOPBACK) + ndlp = NULL; + else + ndlp = piocbq->context_un.ndlp; +@@ -1380,7 +1384,7 @@ static void + __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) + { + struct lpfc_sglq *sglq; +- size_t start_clean = offsetof(struct lpfc_iocbq, iocb); ++ size_t start_clean = offsetof(struct lpfc_iocbq, wqe); + unsigned long iflag = 0; + struct lpfc_sli_ring *pring; + +@@ -1391,7 +1395,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) + + + if (sglq) { +- if (iocbq->iocb_flag & LPFC_IO_NVMET) { ++ if (iocbq->cmd_flag & LPFC_IO_NVMET) { + spin_lock_irqsave(&phba->sli4_hba.sgl_list_lock, + iflag); + sglq->state = SGL_FREED; +@@ -1403,8 +1407,9 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) + goto out; + } + +- if ((iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) && +- (sglq->state != SGL_XRI_ABORTED)) { ++ if ((iocbq->cmd_flag & LPFC_EXCHANGE_BUSY) && ++ (!(unlikely(pci_channel_offline(phba->pcidev)))) && ++ sglq->state != SGL_XRI_ABORTED) { + spin_lock_irqsave(&phba->sli4_hba.sgl_list_lock, + iflag); + +@@ -1439,7 +1444,7 @@ out: + memset((char *)iocbq + start_clean, 0, sizeof(*iocbq) - start_clean); + iocbq->sli4_lxritag = NO_XRI; + iocbq->sli4_xritag = NO_XRI; +- iocbq->iocb_flag &= ~(LPFC_IO_NVME | LPFC_IO_NVMET | LPFC_IO_CMF | ++ iocbq->cmd_flag &= ~(LPFC_IO_NVME | LPFC_IO_NVMET | LPFC_IO_CMF | + LPFC_IO_NVME_LS); + list_add_tail(&iocbq->list, &phba->lpfc_iocb_list); + } +@@ -1529,17 +1534,17 @@ lpfc_sli_cancel_iocbs(struct lpfc_hba *phba, struct list_head *iocblist, + + while (!list_empty(iocblist)) { + list_remove_head(iocblist, piocb, struct lpfc_iocbq, list); +- if (piocb->wqe_cmpl) { +- if (piocb->iocb_flag & LPFC_IO_NVME) ++ if (piocb->cmd_cmpl) { ++ if (piocb->cmd_flag & LPFC_IO_NVME) + lpfc_nvme_cancel_iocb(phba, piocb, + ulpstatus, ulpWord4); + else + lpfc_sli_release_iocbq(phba, piocb); + +- } else if (piocb->iocb_cmpl) { ++ } else if (piocb->cmd_cmpl) { + piocb->iocb.ulpStatus = ulpstatus; + piocb->iocb.un.ulpWord[4] = ulpWord4; +- (piocb->iocb_cmpl) (phba, piocb, piocb); ++ (piocb->cmd_cmpl) (phba, piocb, piocb); + } else { + lpfc_sli_release_iocbq(phba, piocb); + } +@@ -1731,7 +1736,7 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + BUG_ON(!piocb); + + list_add_tail(&piocb->list, &pring->txcmplq); +- piocb->iocb_flag |= LPFC_IO_ON_TXCMPLQ; ++ piocb->cmd_flag |= LPFC_IO_ON_TXCMPLQ; + pring->txcmplq_cnt++; + + if ((unlikely(pring->ringno == LPFC_ELS_RING)) && +@@ -1772,7 +1777,7 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) + * lpfc_cmf_sync_cmpl - Process a CMF_SYNC_WQE cmpl + * @phba: Pointer to HBA context object. + * @cmdiocb: Pointer to driver command iocb object. +- * @cmf_cmpl: Pointer to completed WCQE. ++ * @rspiocb: Pointer to driver response iocb object. + * + * This routine will inform the driver of any BW adjustments we need + * to make. These changes will be picked up during the next CMF +@@ -1781,10 +1786,11 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) + **/ + static void + lpfc_cmf_sync_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, +- struct lpfc_wcqe_complete *cmf_cmpl) ++ struct lpfc_iocbq *rspiocb) + { + union lpfc_wqe128 *wqe; + uint32_t status, info; ++ struct lpfc_wcqe_complete *wcqe = &rspiocb->wcqe_cmpl; + uint64_t bw, bwdif, slop; + uint64_t pcent, bwpcent; + int asig, afpin, sigcnt, fpincnt; +@@ -1792,22 +1798,22 @@ lpfc_cmf_sync_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + char *s; + + /* First check for error */ +- status = bf_get(lpfc_wcqe_c_status, cmf_cmpl); ++ status = bf_get(lpfc_wcqe_c_status, wcqe); + if (status) { + lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, + "6211 CMF_SYNC_WQE Error " + "req_tag x%x status x%x hwstatus x%x " + "tdatap x%x parm x%x\n", +- bf_get(lpfc_wcqe_c_request_tag, cmf_cmpl), +- bf_get(lpfc_wcqe_c_status, cmf_cmpl), +- bf_get(lpfc_wcqe_c_hw_status, cmf_cmpl), +- cmf_cmpl->total_data_placed, +- cmf_cmpl->parameter); ++ bf_get(lpfc_wcqe_c_request_tag, wcqe), ++ bf_get(lpfc_wcqe_c_status, wcqe), ++ bf_get(lpfc_wcqe_c_hw_status, wcqe), ++ wcqe->total_data_placed, ++ wcqe->parameter); + goto out; + } + + /* Gather congestion information on a successful cmpl */ +- info = cmf_cmpl->parameter; ++ info = wcqe->parameter; + phba->cmf_active_info = info; + + /* See if firmware info count is valid or has changed */ +@@ -1816,15 +1822,15 @@ lpfc_cmf_sync_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + else + phba->cmf_info_per_interval = info; + +- tdp = bf_get(lpfc_wcqe_c_cmf_bw, cmf_cmpl); +- cg = bf_get(lpfc_wcqe_c_cmf_cg, cmf_cmpl); ++ tdp = bf_get(lpfc_wcqe_c_cmf_bw, wcqe); ++ cg = bf_get(lpfc_wcqe_c_cmf_cg, wcqe); + + /* Get BW requirement from firmware */ + bw = (uint64_t)tdp * LPFC_CMF_BLK_SIZE; + if (!bw) { + lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, + "6212 CMF_SYNC_WQE x%x: NULL bw\n", +- bf_get(lpfc_wcqe_c_request_tag, cmf_cmpl)); ++ bf_get(lpfc_wcqe_c_request_tag, wcqe)); + goto out; + } + +@@ -1933,7 +1939,7 @@ lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total) + sync_buf = __lpfc_sli_get_iocbq(phba); + if (!sync_buf) { + lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT, +- "6213 No available WQEs for CMF_SYNC_WQE\n"); ++ "6244 No available WQEs for CMF_SYNC_WQE\n"); + ret_val = ENOMEM; + goto out_unlock; + } +@@ -1998,14 +2004,13 @@ initpath: + bf_set(cmf_sync_cqid, &wqe->cmf_sync, LPFC_WQE_CQ_ID_DEFAULT); + + sync_buf->vport = phba->pport; +- sync_buf->wqe_cmpl = lpfc_cmf_sync_cmpl; +- sync_buf->iocb_cmpl = NULL; ++ sync_buf->cmd_cmpl = lpfc_cmf_sync_cmpl; + sync_buf->context1 = NULL; + sync_buf->context2 = NULL; + sync_buf->context3 = NULL; + sync_buf->sli4_xritag = NO_XRI; + +- sync_buf->iocb_flag |= LPFC_IO_CMF; ++ sync_buf->cmd_flag |= LPFC_IO_CMF; + ret_val = lpfc_sli4_issue_wqe(phba, &phba->sli4_hba.hdwq[0], sync_buf); + if (ret_val) + lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, +@@ -2172,7 +2177,7 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + /* + * Set up an iotag + */ +- nextiocb->iocb.ulpIoTag = (nextiocb->iocb_cmpl) ? nextiocb->iotag : 0; ++ nextiocb->iocb.ulpIoTag = (nextiocb->cmd_cmpl) ? nextiocb->iotag : 0; + + + if (pring->ringno == LPFC_ELS_RING) { +@@ -2193,9 +2198,9 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + /* + * If there is no completion routine to call, we can release the + * IOCB buffer back right now. For IOCBs, like QUE_RING_BUF, +- * that have no rsp ring completion, iocb_cmpl MUST be NULL. ++ * that have no rsp ring completion, cmd_cmpl MUST be NULL. + */ +- if (nextiocb->iocb_cmpl) ++ if (nextiocb->cmd_cmpl) + lpfc_sli_ringtxcmpl_put(phba, pring, nextiocb); + else + __lpfc_sli_release_iocbq(phba, nextiocb); +@@ -3549,36 +3554,28 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba, + struct lpfc_iocbq *prspiocb) + { + struct lpfc_iocbq *cmd_iocb = NULL; +- uint16_t iotag; +- spinlock_t *temp_lock = NULL; +- unsigned long iflag = 0; ++ u16 iotag; + + if (phba->sli_rev == LPFC_SLI_REV4) +- temp_lock = &pring->ring_lock; ++ iotag = get_wqe_reqtag(prspiocb); + else +- temp_lock = &phba->hbalock; +- +- spin_lock_irqsave(temp_lock, iflag); +- iotag = prspiocb->iocb.ulpIoTag; ++ iotag = prspiocb->iocb.ulpIoTag; + + if (iotag != 0 && iotag <= phba->sli.last_iotag) { + cmd_iocb = phba->sli.iocbq_lookup[iotag]; +- if (cmd_iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ) { ++ if (cmd_iocb->cmd_flag & LPFC_IO_ON_TXCMPLQ) { + /* remove from txcmpl queue list */ + list_del_init(&cmd_iocb->list); +- cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; ++ cmd_iocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ; + pring->txcmplq_cnt--; +- spin_unlock_irqrestore(temp_lock, iflag); + return cmd_iocb; + } + } + +- spin_unlock_irqrestore(temp_lock, iflag); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "0317 iotag x%x is out of " +- "range: max iotag x%x wd0 x%x\n", +- iotag, phba->sli.last_iotag, +- *(((uint32_t *) &prspiocb->iocb) + 7)); ++ "range: max iotag x%x\n", ++ iotag, phba->sli.last_iotag); + return NULL; + } + +@@ -3599,33 +3596,23 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba, + struct lpfc_sli_ring *pring, uint16_t iotag) + { + struct lpfc_iocbq *cmd_iocb = NULL; +- spinlock_t *temp_lock = NULL; +- unsigned long iflag = 0; +- +- if (phba->sli_rev == LPFC_SLI_REV4) +- temp_lock = &pring->ring_lock; +- else +- temp_lock = &phba->hbalock; + +- spin_lock_irqsave(temp_lock, iflag); + if (iotag != 0 && iotag <= phba->sli.last_iotag) { + cmd_iocb = phba->sli.iocbq_lookup[iotag]; +- if (cmd_iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ) { ++ if (cmd_iocb->cmd_flag & LPFC_IO_ON_TXCMPLQ) { + /* remove from txcmpl queue list */ + list_del_init(&cmd_iocb->list); +- cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; ++ cmd_iocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ; + pring->txcmplq_cnt--; +- spin_unlock_irqrestore(temp_lock, iflag); + return cmd_iocb; + } + } + +- spin_unlock_irqrestore(temp_lock, iflag); + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "0372 iotag x%x lookup error: max iotag (x%x) " +- "iocb_flag x%x\n", ++ "cmd_flag x%x\n", + iotag, phba->sli.last_iotag, +- cmd_iocb ? cmd_iocb->iocb_flag : 0xffff); ++ cmd_iocb ? cmd_iocb->cmd_flag : 0xffff); + return NULL; + } + +@@ -3653,18 +3640,37 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + struct lpfc_iocbq *cmdiocbp; + int rc = 1; + unsigned long iflag; ++ u32 ulp_command, ulp_status, ulp_word4, ulp_context, iotag; + ++ if (phba->sli_rev == LPFC_SLI_REV4) ++ spin_lock_irqsave(&pring->ring_lock, iflag); ++ else ++ spin_lock_irqsave(&phba->hbalock, iflag); + cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq); ++ if (phba->sli_rev == LPFC_SLI_REV4) ++ spin_unlock_irqrestore(&pring->ring_lock, iflag); ++ else ++ spin_unlock_irqrestore(&phba->hbalock, iflag); ++ ++ ulp_command = get_job_cmnd(phba, saveq); ++ ulp_status = get_job_ulpstatus(phba, saveq); ++ ulp_word4 = get_job_word4(phba, saveq); ++ ulp_context = get_job_ulpcontext(phba, saveq); ++ if (phba->sli_rev == LPFC_SLI_REV4) ++ iotag = get_wqe_reqtag(saveq); ++ else ++ iotag = saveq->iocb.ulpIoTag; ++ + if (cmdiocbp) { +- if (cmdiocbp->iocb_cmpl) { ++ ulp_command = get_job_cmnd(phba, cmdiocbp); ++ if (cmdiocbp->cmd_cmpl) { + /* + * If an ELS command failed send an event to mgmt + * application. + */ +- if (saveq->iocb.ulpStatus && ++ if (ulp_status && + (pring->ringno == LPFC_ELS_RING) && +- (cmdiocbp->iocb.ulpCommand == +- CMD_ELS_REQUEST64_CR)) ++ (ulp_command == CMD_ELS_REQUEST64_CR)) + lpfc_send_els_failure_event(phba, + cmdiocbp, saveq); + +@@ -3674,11 +3680,11 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + */ + if (pring->ringno == LPFC_ELS_RING) { + if ((phba->sli_rev < LPFC_SLI_REV4) && +- (cmdiocbp->iocb_flag & ++ (cmdiocbp->cmd_flag & + LPFC_DRIVER_ABORTED)) { + spin_lock_irqsave(&phba->hbalock, + iflag); +- cmdiocbp->iocb_flag &= ++ cmdiocbp->cmd_flag &= + ~LPFC_DRIVER_ABORTED; + spin_unlock_irqrestore(&phba->hbalock, + iflag); +@@ -3693,12 +3699,12 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + */ + spin_lock_irqsave(&phba->hbalock, + iflag); +- saveq->iocb_flag |= LPFC_DELAY_MEM_FREE; ++ saveq->cmd_flag |= LPFC_DELAY_MEM_FREE; + spin_unlock_irqrestore(&phba->hbalock, + iflag); + } + if (phba->sli_rev == LPFC_SLI_REV4) { +- if (saveq->iocb_flag & ++ if (saveq->cmd_flag & + LPFC_EXCHANGE_BUSY) { + /* Set cmdiocb flag for the + * exchange busy so sgl (xri) +@@ -3708,12 +3714,12 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + */ + spin_lock_irqsave( + &phba->hbalock, iflag); +- cmdiocbp->iocb_flag |= ++ cmdiocbp->cmd_flag |= + LPFC_EXCHANGE_BUSY; + spin_unlock_irqrestore( + &phba->hbalock, iflag); + } +- if (cmdiocbp->iocb_flag & ++ if (cmdiocbp->cmd_flag & + LPFC_DRIVER_ABORTED) { + /* + * Clear LPFC_DRIVER_ABORTED +@@ -3722,34 +3728,34 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + */ + spin_lock_irqsave( + &phba->hbalock, iflag); +- cmdiocbp->iocb_flag &= ++ cmdiocbp->cmd_flag &= + ~LPFC_DRIVER_ABORTED; + spin_unlock_irqrestore( + &phba->hbalock, iflag); +- cmdiocbp->iocb.ulpStatus = +- IOSTAT_LOCAL_REJECT; +- cmdiocbp->iocb.un.ulpWord[4] = +- IOERR_ABORT_REQUESTED; ++ set_job_ulpstatus(cmdiocbp, ++ IOSTAT_LOCAL_REJECT); ++ set_job_ulpword4(cmdiocbp, ++ IOERR_ABORT_REQUESTED); + /* +- * For SLI4, irsiocb contains ++ * For SLI4, irspiocb contains + * NO_XRI in sli_xritag, it + * shall not affect releasing + * sgl (xri) process. + */ +- saveq->iocb.ulpStatus = +- IOSTAT_LOCAL_REJECT; +- saveq->iocb.un.ulpWord[4] = +- IOERR_SLI_ABORTED; ++ set_job_ulpstatus(saveq, ++ IOSTAT_LOCAL_REJECT); ++ set_job_ulpword4(saveq, ++ IOERR_SLI_ABORTED); + spin_lock_irqsave( + &phba->hbalock, iflag); +- saveq->iocb_flag |= ++ saveq->cmd_flag |= + LPFC_DELAY_MEM_FREE; + spin_unlock_irqrestore( + &phba->hbalock, iflag); + } + } + } +- (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq); ++ cmdiocbp->cmd_cmpl(phba, cmdiocbp, saveq); + } else + lpfc_sli_release_iocbq(phba, cmdiocbp); + } else { +@@ -3767,12 +3773,8 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + "0322 Ring %d handler: " + "unexpected completion IoTag x%x " + "Data: x%x x%x x%x x%x\n", +- pring->ringno, +- saveq->iocb.ulpIoTag, +- saveq->iocb.ulpStatus, +- saveq->iocb.un.ulpWord[4], +- saveq->iocb.ulpCommand, +- saveq->iocb.ulpContext); ++ pring->ringno, iotag, ulp_status, ++ ulp_word4, ulp_command, ulp_context); + } + } + +@@ -3985,18 +3987,15 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba, + break; + } + +- spin_unlock_irqrestore(&phba->hbalock, iflag); + cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring, + &rspiocbq); +- spin_lock_irqsave(&phba->hbalock, iflag); + if (unlikely(!cmdiocbq)) + break; +- if (cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) +- cmdiocbq->iocb_flag &= ~LPFC_DRIVER_ABORTED; +- if (cmdiocbq->iocb_cmpl) { ++ if (cmdiocbq->cmd_flag & LPFC_DRIVER_ABORTED) ++ cmdiocbq->cmd_flag &= ~LPFC_DRIVER_ABORTED; ++ if (cmdiocbq->cmd_cmpl) { + spin_unlock_irqrestore(&phba->hbalock, iflag); +- (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, +- &rspiocbq); ++ cmdiocbq->cmd_cmpl(phba, cmdiocbq, &rspiocbq); + spin_lock_irqsave(&phba->hbalock, iflag); + } + break; +@@ -4087,155 +4086,159 @@ lpfc_sli_sp_handle_rspiocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + struct lpfc_iocbq *rspiocbp) + { + struct lpfc_iocbq *saveq; +- struct lpfc_iocbq *cmdiocbp; ++ struct lpfc_iocbq *cmdiocb; + struct lpfc_iocbq *next_iocb; +- IOCB_t *irsp = NULL; ++ IOCB_t *irsp; + uint32_t free_saveq; +- uint8_t iocb_cmd_type; ++ u8 cmd_type; + lpfc_iocb_type type; + unsigned long iflag; ++ u32 ulp_status = get_job_ulpstatus(phba, rspiocbp); ++ u32 ulp_word4 = get_job_word4(phba, rspiocbp); ++ u32 ulp_command = get_job_cmnd(phba, rspiocbp); + int rc; + + spin_lock_irqsave(&phba->hbalock, iflag); + /* First add the response iocb to the countinueq list */ +- list_add_tail(&rspiocbp->list, &(pring->iocb_continueq)); ++ list_add_tail(&rspiocbp->list, &pring->iocb_continueq); + pring->iocb_continueq_cnt++; + +- /* Now, determine whether the list is completed for processing */ +- irsp = &rspiocbp->iocb; +- if (irsp->ulpLe) { +- /* +- * By default, the driver expects to free all resources +- * associated with this iocb completion. +- */ +- free_saveq = 1; +- saveq = list_get_first(&pring->iocb_continueq, +- struct lpfc_iocbq, list); +- irsp = &(saveq->iocb); +- list_del_init(&pring->iocb_continueq); +- pring->iocb_continueq_cnt = 0; ++ /* ++ * By default, the driver expects to free all resources ++ * associated with this iocb completion. ++ */ ++ free_saveq = 1; ++ saveq = list_get_first(&pring->iocb_continueq, ++ struct lpfc_iocbq, list); ++ list_del_init(&pring->iocb_continueq); ++ pring->iocb_continueq_cnt = 0; + +- pring->stats.iocb_rsp++; ++ pring->stats.iocb_rsp++; + +- /* +- * If resource errors reported from HBA, reduce +- * queuedepths of the SCSI device. +- */ +- if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && +- ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) == +- IOERR_NO_RESOURCES)) { +- spin_unlock_irqrestore(&phba->hbalock, iflag); +- phba->lpfc_rampdown_queue_depth(phba); +- spin_lock_irqsave(&phba->hbalock, iflag); +- } ++ /* ++ * If resource errors reported from HBA, reduce ++ * queuedepths of the SCSI device. ++ */ ++ if (ulp_status == IOSTAT_LOCAL_REJECT && ++ ((ulp_word4 & IOERR_PARAM_MASK) == ++ IOERR_NO_RESOURCES)) { ++ spin_unlock_irqrestore(&phba->hbalock, iflag); ++ phba->lpfc_rampdown_queue_depth(phba); ++ spin_lock_irqsave(&phba->hbalock, iflag); ++ } + +- if (irsp->ulpStatus) { +- /* Rsp ring <ringno> error: IOCB */ ++ if (ulp_status) { ++ /* Rsp ring <ringno> error: IOCB */ ++ if (phba->sli_rev < LPFC_SLI_REV4) { ++ irsp = &rspiocbp->iocb; + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, +- "0328 Rsp Ring %d error: " ++ "0328 Rsp Ring %d error: ulp_status x%x " ++ "IOCB Data: " ++ "x%08x x%08x x%08x x%08x " ++ "x%08x x%08x x%08x x%08x " ++ "x%08x x%08x x%08x x%08x " ++ "x%08x x%08x x%08x x%08x\n", ++ pring->ringno, ulp_status, ++ get_job_ulpword(rspiocbp, 0), ++ get_job_ulpword(rspiocbp, 1), ++ get_job_ulpword(rspiocbp, 2), ++ get_job_ulpword(rspiocbp, 3), ++ get_job_ulpword(rspiocbp, 4), ++ get_job_ulpword(rspiocbp, 5), ++ *(((uint32_t *)irsp) + 6), ++ *(((uint32_t *)irsp) + 7), ++ *(((uint32_t *)irsp) + 8), ++ *(((uint32_t *)irsp) + 9), ++ *(((uint32_t *)irsp) + 10), ++ *(((uint32_t *)irsp) + 11), ++ *(((uint32_t *)irsp) + 12), ++ *(((uint32_t *)irsp) + 13), ++ *(((uint32_t *)irsp) + 14), ++ *(((uint32_t *)irsp) + 15)); ++ } else { ++ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, ++ "0321 Rsp Ring %d error: " + "IOCB Data: " +- "x%x x%x x%x x%x " +- "x%x x%x x%x x%x " +- "x%x x%x x%x x%x " + "x%x x%x x%x x%x\n", + pring->ringno, +- irsp->un.ulpWord[0], +- irsp->un.ulpWord[1], +- irsp->un.ulpWord[2], +- irsp->un.ulpWord[3], +- irsp->un.ulpWord[4], +- irsp->un.ulpWord[5], +- *(((uint32_t *) irsp) + 6), +- *(((uint32_t *) irsp) + 7), +- *(((uint32_t *) irsp) + 8), +- *(((uint32_t *) irsp) + 9), +- *(((uint32_t *) irsp) + 10), +- *(((uint32_t *) irsp) + 11), +- *(((uint32_t *) irsp) + 12), +- *(((uint32_t *) irsp) + 13), +- *(((uint32_t *) irsp) + 14), +- *(((uint32_t *) irsp) + 15)); ++ rspiocbp->wcqe_cmpl.word0, ++ rspiocbp->wcqe_cmpl.total_data_placed, ++ rspiocbp->wcqe_cmpl.parameter, ++ rspiocbp->wcqe_cmpl.word3); + } ++ } + +- /* +- * Fetch the IOCB command type and call the correct completion +- * routine. Solicited and Unsolicited IOCBs on the ELS ring +- * get freed back to the lpfc_iocb_list by the discovery +- * kernel thread. +- */ +- iocb_cmd_type = irsp->ulpCommand & CMD_IOCB_MASK; +- type = lpfc_sli_iocb_cmd_type(iocb_cmd_type); +- switch (type) { +- case LPFC_SOL_IOCB: +- spin_unlock_irqrestore(&phba->hbalock, iflag); +- rc = lpfc_sli_process_sol_iocb(phba, pring, saveq); +- spin_lock_irqsave(&phba->hbalock, iflag); +- break; +- +- case LPFC_UNSOL_IOCB: +- spin_unlock_irqrestore(&phba->hbalock, iflag); +- rc = lpfc_sli_process_unsol_iocb(phba, pring, saveq); +- spin_lock_irqsave(&phba->hbalock, iflag); +- if (!rc) +- free_saveq = 0; +- break; + +- case LPFC_ABORT_IOCB: +- cmdiocbp = NULL; +- if (irsp->ulpCommand != CMD_XRI_ABORTED_CX) { ++ /* ++ * Fetch the iocb command type and call the correct completion ++ * routine. Solicited and Unsolicited IOCBs on the ELS ring ++ * get freed back to the lpfc_iocb_list by the discovery ++ * kernel thread. ++ */ ++ cmd_type = ulp_command & CMD_IOCB_MASK; ++ type = lpfc_sli_iocb_cmd_type(cmd_type); ++ switch (type) { ++ case LPFC_SOL_IOCB: ++ spin_unlock_irqrestore(&phba->hbalock, iflag); ++ rc = lpfc_sli_process_sol_iocb(phba, pring, saveq); ++ spin_lock_irqsave(&phba->hbalock, iflag); ++ break; ++ case LPFC_UNSOL_IOCB: ++ spin_unlock_irqrestore(&phba->hbalock, iflag); ++ rc = lpfc_sli_process_unsol_iocb(phba, pring, saveq); ++ spin_lock_irqsave(&phba->hbalock, iflag); ++ if (!rc) ++ free_saveq = 0; ++ break; ++ case LPFC_ABORT_IOCB: ++ cmdiocb = NULL; ++ if (ulp_command != CMD_XRI_ABORTED_CX) ++ cmdiocb = lpfc_sli_iocbq_lookup(phba, pring, ++ saveq); ++ if (cmdiocb) { ++ /* Call the specified completion routine */ ++ if (cmdiocb->cmd_cmpl) { + spin_unlock_irqrestore(&phba->hbalock, iflag); +- cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, +- saveq); ++ cmdiocb->cmd_cmpl(phba, cmdiocb, saveq); + spin_lock_irqsave(&phba->hbalock, iflag); +- } +- if (cmdiocbp) { +- /* Call the specified completion routine */ +- if (cmdiocbp->iocb_cmpl) { +- spin_unlock_irqrestore(&phba->hbalock, +- iflag); +- (cmdiocbp->iocb_cmpl)(phba, cmdiocbp, +- saveq); +- spin_lock_irqsave(&phba->hbalock, +- iflag); +- } else +- __lpfc_sli_release_iocbq(phba, +- cmdiocbp); +- } +- break; +- +- case LPFC_UNKNOWN_IOCB: +- if (irsp->ulpCommand == CMD_ADAPTER_MSG) { +- char adaptermsg[LPFC_MAX_ADPTMSG]; +- memset(adaptermsg, 0, LPFC_MAX_ADPTMSG); +- memcpy(&adaptermsg[0], (uint8_t *)irsp, +- MAX_MSG_DATA); +- dev_warn(&((phba->pcidev)->dev), +- "lpfc%d: %s\n", +- phba->brd_no, adaptermsg); + } else { +- /* Unknown IOCB command */ +- lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, +- "0335 Unknown IOCB " +- "command Data: x%x " +- "x%x x%x x%x\n", +- irsp->ulpCommand, +- irsp->ulpStatus, +- irsp->ulpIoTag, +- irsp->ulpContext); ++ __lpfc_sli_release_iocbq(phba, cmdiocb); + } +- break; + } ++ break; ++ case LPFC_UNKNOWN_IOCB: ++ if (ulp_command == CMD_ADAPTER_MSG) { ++ char adaptermsg[LPFC_MAX_ADPTMSG]; ++ ++ memset(adaptermsg, 0, LPFC_MAX_ADPTMSG); ++ memcpy(&adaptermsg[0], (uint8_t *)&rspiocbp->wqe, ++ MAX_MSG_DATA); ++ dev_warn(&((phba->pcidev)->dev), ++ "lpfc%d: %s\n", ++ phba->brd_no, adaptermsg); ++ } else { ++ /* Unknown command */ ++ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, ++ "0335 Unknown IOCB " ++ "command Data: x%x " ++ "x%x x%x x%x\n", ++ ulp_command, ++ ulp_status, ++ get_wqe_reqtag(rspiocbp), ++ get_job_ulpcontext(phba, rspiocbp)); ++ } ++ break; ++ } + +- if (free_saveq) { +- list_for_each_entry_safe(rspiocbp, next_iocb, +- &saveq->list, list) { +- list_del_init(&rspiocbp->list); +- __lpfc_sli_release_iocbq(phba, rspiocbp); +- } +- __lpfc_sli_release_iocbq(phba, saveq); ++ if (free_saveq) { ++ list_for_each_entry_safe(rspiocbp, next_iocb, ++ &saveq->list, list) { ++ list_del_init(&rspiocbp->list); ++ __lpfc_sli_release_iocbq(phba, rspiocbp); + } +- rspiocbp = NULL; ++ __lpfc_sli_release_iocbq(phba, saveq); + } ++ rspiocbp = NULL; + spin_unlock_irqrestore(&phba->hbalock, iflag); + return rspiocbp; + } +@@ -4428,8 +4431,8 @@ lpfc_sli_handle_slow_ring_event_s4(struct lpfc_hba *phba, + irspiocbq = container_of(cq_event, struct lpfc_iocbq, + cq_event); + /* Translate ELS WCQE to response IOCBQ */ +- irspiocbq = lpfc_sli4_els_wcqe_to_rspiocbq(phba, +- irspiocbq); ++ irspiocbq = lpfc_sli4_els_preprocess_rspiocbq(phba, ++ irspiocbq); + if (irspiocbq) + lpfc_sli_sp_handle_rspiocb(phba, pring, + irspiocbq); +@@ -4572,7 +4575,7 @@ lpfc_sli_flush_io_rings(struct lpfc_hba *phba) + list_splice_init(&pring->txq, &txq); + list_for_each_entry_safe(piocb, next_iocb, + &pring->txcmplq, list) +- piocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; ++ piocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ; + /* Retrieve everything on the txcmplq */ + list_splice_init(&pring->txcmplq, &txcmplq); + pring->txq_cnt = 0; +@@ -4583,10 +4586,12 @@ lpfc_sli_flush_io_rings(struct lpfc_hba *phba) + lpfc_sli_cancel_iocbs(phba, &txq, + IOSTAT_LOCAL_REJECT, + IOERR_SLI_DOWN); +- /* Flush the txcmpq */ ++ /* Flush the txcmplq */ + lpfc_sli_cancel_iocbs(phba, &txcmplq, + IOSTAT_LOCAL_REJECT, + IOERR_SLI_DOWN); ++ if (unlikely(pci_channel_offline(phba->pcidev))) ++ lpfc_sli4_io_xri_aborted(phba, NULL, 0); + } + } else { + pring = &psli->sli3_ring[LPFC_FCP_RING]; +@@ -4596,7 +4601,7 @@ lpfc_sli_flush_io_rings(struct lpfc_hba *phba) + list_splice_init(&pring->txq, &txq); + list_for_each_entry_safe(piocb, next_iocb, + &pring->txcmplq, list) +- piocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; ++ piocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ; + /* Retrieve everything on the txcmplq */ + list_splice_init(&pring->txcmplq, &txcmplq); + pring->txq_cnt = 0; +@@ -10112,7 +10117,7 @@ __lpfc_sli_issue_iocb_s3(struct lpfc_hba *phba, uint32_t ring_number, + + lockdep_assert_held(&phba->hbalock); + +- if (piocb->iocb_cmpl && (!piocb->vport) && ++ if (piocb->cmd_cmpl && (!piocb->vport) && + (piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) && + (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) { + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, +@@ -10164,10 +10169,10 @@ __lpfc_sli_issue_iocb_s3(struct lpfc_hba *phba, uint32_t ring_number, + case CMD_QUE_RING_BUF64_CN: + /* + * For IOCBs, like QUE_RING_BUF, that have no rsp ring +- * completion, iocb_cmpl MUST be 0. ++ * completion, cmd_cmpl MUST be 0. + */ +- if (piocb->iocb_cmpl) +- piocb->iocb_cmpl = NULL; ++ if (piocb->cmd_cmpl) ++ piocb->cmd_cmpl = NULL; + fallthrough; + case CMD_CREATE_XRI_CR: + case CMD_CLOSE_XRI_CN: +@@ -10358,9 +10363,9 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, + + fip = phba->hba_flag & HBA_FIP_SUPPORT; + /* The fcp commands will set command type */ +- if (iocbq->iocb_flag & LPFC_IO_FCP) ++ if (iocbq->cmd_flag & LPFC_IO_FCP) + command_type = FCP_COMMAND; +- else if (fip && (iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK)) ++ else if (fip && (iocbq->cmd_flag & LPFC_FIP_ELS_ID_MASK)) + command_type = ELS_COMMAND_FIP; + else + command_type = ELS_COMMAND_NON_FIP; +@@ -10405,7 +10410,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, + + switch (iocbq->iocb.ulpCommand) { + case CMD_ELS_REQUEST64_CR: +- if (iocbq->iocb_flag & LPFC_IO_LIBDFC) ++ if (iocbq->cmd_flag & LPFC_IO_LIBDFC) + ndlp = iocbq->context_un.ndlp; + else + ndlp = (struct lpfc_nodelist *)iocbq->context1; +@@ -10432,7 +10437,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, + bf_set(wqe_pu, &wqe->els_req.wqe_com, 0); + /* CCP CCPE PV PRI in word10 were set in the memcpy */ + if (command_type == ELS_COMMAND_FIP) +- els_id = ((iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK) ++ els_id = ((iocbq->cmd_flag & LPFC_FIP_ELS_ID_MASK) + >> LPFC_FIP_ELS_ID_SHIFT); + pcmd = (uint32_t *) (((struct lpfc_dmabuf *) + iocbq->context2)->virt); +@@ -10534,7 +10539,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, + LPFC_WQE_LENLOC_WORD4); + bf_set(wqe_pu, &wqe->fcp_iwrite.wqe_com, iocbq->iocb.ulpPU); + bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 1); +- if (iocbq->iocb_flag & LPFC_IO_OAS) { ++ if (iocbq->cmd_flag & LPFC_IO_OAS) { + bf_set(wqe_oas, &wqe->fcp_iwrite.wqe_com, 1); + bf_set(wqe_ccpe, &wqe->fcp_iwrite.wqe_com, 1); + if (iocbq->priority) { +@@ -10598,7 +10603,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, + LPFC_WQE_LENLOC_WORD4); + bf_set(wqe_pu, &wqe->fcp_iread.wqe_com, iocbq->iocb.ulpPU); + bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 1); +- if (iocbq->iocb_flag & LPFC_IO_OAS) { ++ if (iocbq->cmd_flag & LPFC_IO_OAS) { + bf_set(wqe_oas, &wqe->fcp_iread.wqe_com, 1); + bf_set(wqe_ccpe, &wqe->fcp_iread.wqe_com, 1); + if (iocbq->priority) { +@@ -10661,7 +10666,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, + LPFC_WQE_LENLOC_NONE); + bf_set(wqe_erp, &wqe->fcp_icmd.wqe_com, + iocbq->iocb.ulpFCP2Rcvy); +- if (iocbq->iocb_flag & LPFC_IO_OAS) { ++ if (iocbq->cmd_flag & LPFC_IO_OAS) { + bf_set(wqe_oas, &wqe->fcp_icmd.wqe_com, 1); + bf_set(wqe_ccpe, &wqe->fcp_icmd.wqe_com, 1); + if (iocbq->priority) { +@@ -10795,7 +10800,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, + abrt_iotag = iocbq->iocb.un.acxri.abortContextTag; + if (abrt_iotag != 0 && abrt_iotag <= phba->sli.last_iotag) { + abrtiocbq = phba->sli.iocbq_lookup[abrt_iotag]; +- fip = abrtiocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK; ++ fip = abrtiocbq->cmd_flag & LPFC_FIP_ELS_ID_MASK; + } else + fip = 0; + +@@ -10904,13 +10909,13 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, + return IOCB_ERROR; + } + +- if (iocbq->iocb_flag & LPFC_IO_DIF_PASS) ++ if (iocbq->cmd_flag & LPFC_IO_DIF_PASS) + bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_PASSTHRU); +- else if (iocbq->iocb_flag & LPFC_IO_DIF_STRIP) ++ else if (iocbq->cmd_flag & LPFC_IO_DIF_STRIP) + bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_STRIP); +- else if (iocbq->iocb_flag & LPFC_IO_DIF_INSERT) ++ else if (iocbq->cmd_flag & LPFC_IO_DIF_INSERT) + bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_INSERT); +- iocbq->iocb_flag &= ~(LPFC_IO_DIF_PASS | LPFC_IO_DIF_STRIP | ++ iocbq->cmd_flag &= ~(LPFC_IO_DIF_PASS | LPFC_IO_DIF_STRIP | + LPFC_IO_DIF_INSERT); + bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag); + bf_set(wqe_reqtag, &wqe->generic.wqe_com, iocbq->iotag); +@@ -10930,7 +10935,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, + * @flag: Flag indicating if this command can be put into txq. + * + * __lpfc_sli_issue_fcp_io_s3 is wrapper function to invoke lockless func to +- * send an iocb command to an HBA with SLI-4 interface spec. ++ * send an iocb command to an HBA with SLI-3 interface spec. + * + * This function takes the hbalock before invoking the lockless version. + * The function will return success after it successfully submit the wqe to +@@ -10971,7 +10976,17 @@ __lpfc_sli_issue_fcp_io_s4(struct lpfc_hba *phba, uint32_t ring_number, + int rc; + struct lpfc_io_buf *lpfc_cmd = + (struct lpfc_io_buf *)piocb->context1; +- union lpfc_wqe128 *wqe = &piocb->wqe; ++ ++ lpfc_prep_embed_io(phba, lpfc_cmd); ++ rc = lpfc_sli4_issue_wqe(phba, lpfc_cmd->hdwq, piocb); ++ return rc; ++} ++ ++void ++lpfc_prep_embed_io(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) ++{ ++ struct lpfc_iocbq *piocb = &lpfc_cmd->cur_iocbq; ++ union lpfc_wqe128 *wqe = &lpfc_cmd->cur_iocbq.wqe; + struct sli4_sge *sgl; + + /* 128 byte wqe support here */ +@@ -11009,7 +11024,7 @@ __lpfc_sli_issue_fcp_io_s4(struct lpfc_hba *phba, uint32_t ring_number, + } + + /* add the VMID tags as per switch response */ +- if (unlikely(piocb->iocb_flag & LPFC_IO_VMID)) { ++ if (unlikely(piocb->cmd_flag & LPFC_IO_VMID)) { + if (phba->pport->vmid_priority_tagging) { + bf_set(wqe_ccpe, &wqe->fcp_iwrite.wqe_com, 1); + bf_set(wqe_ccp, &wqe->fcp_iwrite.wqe_com, +@@ -11020,8 +11035,6 @@ __lpfc_sli_issue_fcp_io_s4(struct lpfc_hba *phba, uint32_t ring_number, + wqe->words[31] = piocb->vmid_tag.app_id; + } + } +- rc = lpfc_sli4_issue_wqe(phba, lpfc_cmd->hdwq, piocb); +- return rc; + } + + /** +@@ -11043,13 +11056,14 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, + struct lpfc_iocbq *piocb, uint32_t flag) + { + struct lpfc_sglq *sglq; +- union lpfc_wqe128 wqe; ++ union lpfc_wqe128 *wqe; + struct lpfc_queue *wq; + struct lpfc_sli_ring *pring; ++ u32 ulp_command = get_job_cmnd(phba, piocb); + + /* Get the WQ */ +- if ((piocb->iocb_flag & LPFC_IO_FCP) || +- (piocb->iocb_flag & LPFC_USE_FCPWQIDX)) { ++ if ((piocb->cmd_flag & LPFC_IO_FCP) || ++ (piocb->cmd_flag & LPFC_USE_FCPWQIDX)) { + wq = phba->sli4_hba.hdwq[piocb->hba_wqidx].io_wq; + } else { + wq = phba->sli4_hba.els_wq; +@@ -11063,10 +11077,9 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, + */ + + lockdep_assert_held(&pring->ring_lock); +- ++ wqe = &piocb->wqe; + if (piocb->sli4_xritag == NO_XRI) { +- if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN || +- piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN) ++ if (ulp_command == CMD_ABORT_XRI_WQE) + sglq = NULL; + else { + if (!list_empty(&pring->txq)) { +@@ -11090,7 +11103,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, + } + } + } +- } else if (piocb->iocb_flag & LPFC_IO_FCP) { ++ } else if (piocb->cmd_flag & LPFC_IO_FCP) { + /* These IO's already have an XRI and a mapped sgl. */ + sglq = NULL; + } +@@ -11107,14 +11120,24 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, + if (sglq) { + piocb->sli4_lxritag = sglq->sli4_lxritag; + piocb->sli4_xritag = sglq->sli4_xritag; +- if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocb, sglq)) ++ ++ /* ABTS sent by initiator to CT exchange, the ++ * RX_ID field will be filled with the newly ++ * allocated responder XRI. ++ */ ++ if (ulp_command == CMD_XMIT_BLS_RSP64_CX && ++ piocb->abort_bls == LPFC_ABTS_UNSOL_INT) ++ bf_set(xmit_bls_rsp64_rxid, &wqe->xmit_bls_rsp, ++ piocb->sli4_xritag); ++ ++ bf_set(wqe_xri_tag, &wqe->generic.wqe_com, ++ piocb->sli4_xritag); ++ ++ if (lpfc_wqe_bpl2sgl(phba, piocb, sglq) == NO_XRI) + return IOCB_ERROR; + } + +- if (lpfc_sli4_iocb2wqe(phba, piocb, &wqe)) +- return IOCB_ERROR; +- +- if (lpfc_sli4_wq_put(wq, &wqe)) ++ if (lpfc_sli4_wq_put(wq, wqe)) + return IOCB_ERROR; + lpfc_sli_ringtxcmpl_put(phba, pring, piocb); + +@@ -11207,14 +11230,14 @@ lpfc_sli4_calc_ring(struct lpfc_hba *phba, struct lpfc_iocbq *piocb) + { + struct lpfc_io_buf *lpfc_cmd; + +- if (piocb->iocb_flag & (LPFC_IO_FCP | LPFC_USE_FCPWQIDX)) { ++ if (piocb->cmd_flag & (LPFC_IO_FCP | LPFC_USE_FCPWQIDX)) { + if (unlikely(!phba->sli4_hba.hdwq)) + return NULL; + /* + * for abort iocb hba_wqidx should already + * be setup based on what work queue we used. + */ +- if (!(piocb->iocb_flag & LPFC_USE_FCPWQIDX)) { ++ if (!(piocb->cmd_flag & LPFC_USE_FCPWQIDX)) { + lpfc_cmd = (struct lpfc_io_buf *)piocb->context1; + piocb->hba_wqidx = lpfc_cmd->hdwq_no; + } +@@ -12356,14 +12379,14 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + icmd = &cmdiocb->iocb; + if (icmd->ulpCommand == CMD_ABORT_XRI_CN || + icmd->ulpCommand == CMD_CLOSE_XRI_CN || +- cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) ++ cmdiocb->cmd_flag & LPFC_DRIVER_ABORTED) + return IOCB_ABORTING; + + if (!pring) { +- if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) +- cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; ++ if (cmdiocb->cmd_flag & LPFC_IO_FABRIC) ++ cmdiocb->fabric_cmd_cmpl = lpfc_ignore_els_cmpl; + else +- cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl; ++ cmdiocb->cmd_cmpl = lpfc_ignore_els_cmpl; + return retval; + } + +@@ -12373,10 +12396,10 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + */ + if ((vport->load_flag & FC_UNLOADING) && + pring->ringno == LPFC_ELS_RING) { +- if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) +- cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; ++ if (cmdiocb->cmd_flag & LPFC_IO_FABRIC) ++ cmdiocb->fabric_cmd_cmpl = lpfc_ignore_els_cmpl; + else +- cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl; ++ cmdiocb->cmd_cmpl = lpfc_ignore_els_cmpl; + return retval; + } + +@@ -12388,7 +12411,7 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + /* This signals the response to set the correct status + * before calling the completion handler + */ +- cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED; ++ cmdiocb->cmd_flag |= LPFC_DRIVER_ABORTED; + + iabt = &abtsiocbp->iocb; + iabt->un.acxri.abortType = ABORT_TYPE_ABTS; +@@ -12409,10 +12432,10 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + + /* ABTS WQE must go to the same WQ as the WQE to be aborted */ + abtsiocbp->hba_wqidx = cmdiocb->hba_wqidx; +- if (cmdiocb->iocb_flag & LPFC_IO_FCP) +- abtsiocbp->iocb_flag |= (LPFC_IO_FCP | LPFC_USE_FCPWQIDX); +- if (cmdiocb->iocb_flag & LPFC_IO_FOF) +- abtsiocbp->iocb_flag |= LPFC_IO_FOF; ++ if (cmdiocb->cmd_flag & LPFC_IO_FCP) ++ abtsiocbp->cmd_flag |= (LPFC_IO_FCP | LPFC_USE_FCPWQIDX); ++ if (cmdiocb->cmd_flag & LPFC_IO_FOF) ++ abtsiocbp->cmd_flag |= LPFC_IO_FOF; + + if (phba->link_state < LPFC_LINK_UP || + (phba->sli_rev == LPFC_SLI_REV4 && +@@ -12422,9 +12445,9 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + iabt->ulpCommand = CMD_ABORT_XRI_CN; + + if (cmpl) +- abtsiocbp->iocb_cmpl = cmpl; ++ abtsiocbp->cmd_cmpl = cmpl; + else +- abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl; ++ abtsiocbp->cmd_cmpl = lpfc_sli_abort_els_cmpl; + abtsiocbp->vport = vport; + + if (phba->sli_rev == LPFC_SLI_REV4) { +@@ -12451,7 +12474,7 @@ abort_iotag_exit: + abtsiocbp->iotag, retval); + + if (retval) { +- cmdiocb->iocb_flag &= ~LPFC_DRIVER_ABORTED; ++ cmdiocb->cmd_flag &= ~LPFC_DRIVER_ABORTED; + __lpfc_sli_release_iocbq(phba, abtsiocbp); + } + +@@ -12519,9 +12542,9 @@ lpfc_sli_validate_fcp_iocb_for_abort(struct lpfc_iocbq *iocbq, + * can't be premarked as driver aborted, nor be an ABORT iocb itself + */ + icmd = &iocbq->iocb; +- if (!(iocbq->iocb_flag & LPFC_IO_FCP) || +- !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ) || +- (iocbq->iocb_flag & LPFC_DRIVER_ABORTED) || ++ if (!(iocbq->cmd_flag & LPFC_IO_FCP) || ++ !(iocbq->cmd_flag & LPFC_IO_ON_TXCMPLQ) || ++ (iocbq->cmd_flag & LPFC_DRIVER_ABORTED) || + (icmd->ulpCommand == CMD_ABORT_XRI_CN || + icmd->ulpCommand == CMD_CLOSE_XRI_CN)) + return -EINVAL; +@@ -12625,8 +12648,8 @@ lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id, + + if (!iocbq || iocbq->vport != vport) + continue; +- if (!(iocbq->iocb_flag & LPFC_IO_FCP) || +- !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ)) ++ if (!(iocbq->cmd_flag & LPFC_IO_FCP) || ++ !(iocbq->cmd_flag & LPFC_IO_ON_TXCMPLQ)) + continue; + + /* Include counting outstanding aborts */ +@@ -12852,8 +12875,8 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, + * If the iocbq is already being aborted, don't take a second + * action, but do count it. + */ +- if ((iocbq->iocb_flag & LPFC_DRIVER_ABORTED) || +- !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ)) { ++ if ((iocbq->cmd_flag & LPFC_DRIVER_ABORTED) || ++ !(iocbq->cmd_flag & LPFC_IO_ON_TXCMPLQ)) { + if (phba->sli_rev == LPFC_SLI_REV4) + spin_unlock(&pring_s4->ring_lock); + spin_unlock(&lpfc_cmd->buf_lock); +@@ -12883,10 +12906,10 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, + + /* ABTS WQE must go to the same WQ as the WQE to be aborted */ + abtsiocbq->hba_wqidx = iocbq->hba_wqidx; +- if (iocbq->iocb_flag & LPFC_IO_FCP) +- abtsiocbq->iocb_flag |= LPFC_USE_FCPWQIDX; +- if (iocbq->iocb_flag & LPFC_IO_FOF) +- abtsiocbq->iocb_flag |= LPFC_IO_FOF; ++ if (iocbq->cmd_flag & LPFC_IO_FCP) ++ abtsiocbq->cmd_flag |= LPFC_USE_FCPWQIDX; ++ if (iocbq->cmd_flag & LPFC_IO_FOF) ++ abtsiocbq->cmd_flag |= LPFC_IO_FOF; + + ndlp = lpfc_cmd->rdata->pnode; + +@@ -12897,13 +12920,13 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, + abtsiocbq->iocb.ulpCommand = CMD_CLOSE_XRI_CN; + + /* Setup callback routine and issue the command. */ +- abtsiocbq->iocb_cmpl = lpfc_sli_abort_fcp_cmpl; ++ abtsiocbq->cmd_cmpl = lpfc_sli_abort_fcp_cmpl; + + /* + * Indicate the IO is being aborted by the driver and set + * the caller's flag into the aborted IO. + */ +- iocbq->iocb_flag |= LPFC_DRIVER_ABORTED; ++ iocbq->cmd_flag |= LPFC_DRIVER_ABORTED; + + if (phba->sli_rev == LPFC_SLI_REV4) { + ret_val = __lpfc_sli_issue_iocb(phba, pring_s4->ringno, +@@ -12950,9 +12973,10 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, + wait_queue_head_t *pdone_q; + unsigned long iflags; + struct lpfc_io_buf *lpfc_cmd; ++ size_t offset = offsetof(struct lpfc_iocbq, wqe); + + spin_lock_irqsave(&phba->hbalock, iflags); +- if (cmdiocbq->iocb_flag & LPFC_IO_WAKE_TMO) { ++ if (cmdiocbq->cmd_flag & LPFC_IO_WAKE_TMO) { + + /* + * A time out has occurred for the iocb. If a time out +@@ -12961,26 +12985,27 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, + */ + + spin_unlock_irqrestore(&phba->hbalock, iflags); +- cmdiocbq->iocb_cmpl = cmdiocbq->wait_iocb_cmpl; +- cmdiocbq->wait_iocb_cmpl = NULL; +- if (cmdiocbq->iocb_cmpl) +- (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, NULL); ++ cmdiocbq->cmd_cmpl = cmdiocbq->wait_cmd_cmpl; ++ cmdiocbq->wait_cmd_cmpl = NULL; ++ if (cmdiocbq->cmd_cmpl) ++ cmdiocbq->cmd_cmpl(phba, cmdiocbq, NULL); + else + lpfc_sli_release_iocbq(phba, cmdiocbq); + return; + } + +- cmdiocbq->iocb_flag |= LPFC_IO_WAKE; ++ /* Copy the contents of the local rspiocb into the caller's buffer. */ ++ cmdiocbq->cmd_flag |= LPFC_IO_WAKE; + if (cmdiocbq->context2 && rspiocbq) +- memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb, +- &rspiocbq->iocb, sizeof(IOCB_t)); ++ memcpy((char *)cmdiocbq->context2 + offset, ++ (char *)rspiocbq + offset, sizeof(*rspiocbq) - offset); + + /* Set the exchange busy flag for task management commands */ +- if ((cmdiocbq->iocb_flag & LPFC_IO_FCP) && +- !(cmdiocbq->iocb_flag & LPFC_IO_LIBDFC)) { ++ if ((cmdiocbq->cmd_flag & LPFC_IO_FCP) && ++ !(cmdiocbq->cmd_flag & LPFC_IO_LIBDFC)) { + lpfc_cmd = container_of(cmdiocbq, struct lpfc_io_buf, +- cur_iocbq); +- if (rspiocbq && (rspiocbq->iocb_flag & LPFC_EXCHANGE_BUSY)) ++ cur_iocbq); ++ if (rspiocbq && (rspiocbq->cmd_flag & LPFC_EXCHANGE_BUSY)) + lpfc_cmd->flags |= LPFC_SBUF_XBUSY; + else + lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY; +@@ -12999,7 +13024,7 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, + * @piocbq: Pointer to command iocb. + * @flag: Flag to test. + * +- * This routine grabs the hbalock and then test the iocb_flag to ++ * This routine grabs the hbalock and then test the cmd_flag to + * see if the passed in flag is set. + * Returns: + * 1 if flag is set. +@@ -13013,7 +13038,7 @@ lpfc_chk_iocb_flg(struct lpfc_hba *phba, + int ret; + + spin_lock_irqsave(&phba->hbalock, iflags); +- ret = piocbq->iocb_flag & flag; ++ ret = piocbq->cmd_flag & flag; + spin_unlock_irqrestore(&phba->hbalock, iflags); + return ret; + +@@ -13028,14 +13053,14 @@ lpfc_chk_iocb_flg(struct lpfc_hba *phba, + * @timeout: Timeout in number of seconds. + * + * This function issues the iocb to firmware and waits for the +- * iocb to complete. The iocb_cmpl field of the shall be used ++ * iocb to complete. The cmd_cmpl field of the shall be used + * to handle iocbs which time out. If the field is NULL, the + * function shall free the iocbq structure. If more clean up is + * needed, the caller is expected to provide a completion function + * that will provide the needed clean up. If the iocb command is + * not completed within timeout seconds, the function will either +- * free the iocbq structure (if iocb_cmpl == NULL) or execute the +- * completion function set in the iocb_cmpl field and then return ++ * free the iocbq structure (if cmd_cmpl == NULL) or execute the ++ * completion function set in the cmd_cmpl field and then return + * a status of IOCB_TIMEDOUT. The caller should not free the iocb + * resources if this function returns IOCB_TIMEDOUT. + * The function waits for the iocb completion using an +@@ -13047,7 +13072,7 @@ lpfc_chk_iocb_flg(struct lpfc_hba *phba, + * This function assumes that the iocb completions occur while + * this function sleep. So, this function cannot be called from + * the thread which process iocb completion for this ring. +- * This function clears the iocb_flag of the iocb object before ++ * This function clears the cmd_flag of the iocb object before + * issuing the iocb and the iocb completion handler sets this + * flag and wakes this thread when the iocb completes. + * The contents of the response iocb will be copied to prspiocbq +@@ -13087,10 +13112,10 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, + piocb->context2 = prspiocbq; + } + +- piocb->wait_iocb_cmpl = piocb->iocb_cmpl; +- piocb->iocb_cmpl = lpfc_sli_wake_iocb_wait; ++ piocb->wait_cmd_cmpl = piocb->cmd_cmpl; ++ piocb->cmd_cmpl = lpfc_sli_wake_iocb_wait; + piocb->context_un.wait_queue = &done_q; +- piocb->iocb_flag &= ~(LPFC_IO_WAKE | LPFC_IO_WAKE_TMO); ++ piocb->cmd_flag &= ~(LPFC_IO_WAKE | LPFC_IO_WAKE_TMO); + + if (phba->cfg_poll & DISABLE_FCP_RING_INT) { + if (lpfc_readl(phba->HCregaddr, &creg_val)) +@@ -13108,7 +13133,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, + lpfc_chk_iocb_flg(phba, piocb, LPFC_IO_WAKE), + timeout_req); + spin_lock_irqsave(&phba->hbalock, iflags); +- if (!(piocb->iocb_flag & LPFC_IO_WAKE)) { ++ if (!(piocb->cmd_flag & LPFC_IO_WAKE)) { + + /* + * IOCB timed out. Inform the wake iocb wait +@@ -13116,7 +13141,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, + */ + + iocb_completed = false; +- piocb->iocb_flag |= LPFC_IO_WAKE_TMO; ++ piocb->cmd_flag |= LPFC_IO_WAKE_TMO; + } + spin_unlock_irqrestore(&phba->hbalock, iflags); + if (iocb_completed) { +@@ -13171,7 +13196,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, + piocb->context2 = NULL; + + piocb->context_un.wait_queue = NULL; +- piocb->iocb_cmpl = NULL; ++ piocb->cmd_cmpl = NULL; + return retval; + } + +@@ -14112,135 +14137,19 @@ void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *phba) + } + + /** +- * lpfc_sli4_iocb_param_transfer - Transfer pIocbOut and cmpl status to pIocbIn +- * @phba: pointer to lpfc hba data structure +- * @pIocbIn: pointer to the rspiocbq +- * @pIocbOut: pointer to the cmdiocbq +- * @wcqe: pointer to the complete wcqe +- * +- * This routine transfers the fields of a command iocbq to a response iocbq +- * by copying all the IOCB fields from command iocbq and transferring the +- * completion status information from the complete wcqe. +- **/ +-static void +-lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba, +- struct lpfc_iocbq *pIocbIn, +- struct lpfc_iocbq *pIocbOut, +- struct lpfc_wcqe_complete *wcqe) +-{ +- int numBdes, i; +- unsigned long iflags; +- uint32_t status, max_response; +- struct lpfc_dmabuf *dmabuf; +- struct ulp_bde64 *bpl, bde; +- size_t offset = offsetof(struct lpfc_iocbq, iocb); +- +- memcpy((char *)pIocbIn + offset, (char *)pIocbOut + offset, +- sizeof(struct lpfc_iocbq) - offset); +- /* Map WCQE parameters into irspiocb parameters */ +- status = bf_get(lpfc_wcqe_c_status, wcqe); +- pIocbIn->iocb.ulpStatus = (status & LPFC_IOCB_STATUS_MASK); +- if (pIocbOut->iocb_flag & LPFC_IO_FCP) +- if (pIocbIn->iocb.ulpStatus == IOSTAT_FCP_RSP_ERROR) +- pIocbIn->iocb.un.fcpi.fcpi_parm = +- pIocbOut->iocb.un.fcpi.fcpi_parm - +- wcqe->total_data_placed; +- else +- pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; +- else { +- pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; +- switch (pIocbOut->iocb.ulpCommand) { +- case CMD_ELS_REQUEST64_CR: +- dmabuf = (struct lpfc_dmabuf *)pIocbOut->context3; +- bpl = (struct ulp_bde64 *)dmabuf->virt; +- bde.tus.w = le32_to_cpu(bpl[1].tus.w); +- max_response = bde.tus.f.bdeSize; +- break; +- case CMD_GEN_REQUEST64_CR: +- max_response = 0; +- if (!pIocbOut->context3) +- break; +- numBdes = pIocbOut->iocb.un.genreq64.bdl.bdeSize/ +- sizeof(struct ulp_bde64); +- dmabuf = (struct lpfc_dmabuf *)pIocbOut->context3; +- bpl = (struct ulp_bde64 *)dmabuf->virt; +- for (i = 0; i < numBdes; i++) { +- bde.tus.w = le32_to_cpu(bpl[i].tus.w); +- if (bde.tus.f.bdeFlags != BUFF_TYPE_BDE_64) +- max_response += bde.tus.f.bdeSize; +- } +- break; +- default: +- max_response = wcqe->total_data_placed; +- break; +- } +- if (max_response < wcqe->total_data_placed) +- pIocbIn->iocb.un.genreq64.bdl.bdeSize = max_response; +- else +- pIocbIn->iocb.un.genreq64.bdl.bdeSize = +- wcqe->total_data_placed; +- } +- +- /* Convert BG errors for completion status */ +- if (status == CQE_STATUS_DI_ERROR) { +- pIocbIn->iocb.ulpStatus = IOSTAT_LOCAL_REJECT; +- +- if (bf_get(lpfc_wcqe_c_bg_edir, wcqe)) +- pIocbIn->iocb.un.ulpWord[4] = IOERR_RX_DMA_FAILED; +- else +- pIocbIn->iocb.un.ulpWord[4] = IOERR_TX_DMA_FAILED; +- +- pIocbIn->iocb.unsli3.sli3_bg.bgstat = 0; +- if (bf_get(lpfc_wcqe_c_bg_ge, wcqe)) /* Guard Check failed */ +- pIocbIn->iocb.unsli3.sli3_bg.bgstat |= +- BGS_GUARD_ERR_MASK; +- if (bf_get(lpfc_wcqe_c_bg_ae, wcqe)) /* App Tag Check failed */ +- pIocbIn->iocb.unsli3.sli3_bg.bgstat |= +- BGS_APPTAG_ERR_MASK; +- if (bf_get(lpfc_wcqe_c_bg_re, wcqe)) /* Ref Tag Check failed */ +- pIocbIn->iocb.unsli3.sli3_bg.bgstat |= +- BGS_REFTAG_ERR_MASK; +- +- /* Check to see if there was any good data before the error */ +- if (bf_get(lpfc_wcqe_c_bg_tdpv, wcqe)) { +- pIocbIn->iocb.unsli3.sli3_bg.bgstat |= +- BGS_HI_WATER_MARK_PRESENT_MASK; +- pIocbIn->iocb.unsli3.sli3_bg.bghm = +- wcqe->total_data_placed; +- } +- +- /* +- * Set ALL the error bits to indicate we don't know what +- * type of error it is. +- */ +- if (!pIocbIn->iocb.unsli3.sli3_bg.bgstat) +- pIocbIn->iocb.unsli3.sli3_bg.bgstat |= +- (BGS_REFTAG_ERR_MASK | BGS_APPTAG_ERR_MASK | +- BGS_GUARD_ERR_MASK); +- } +- +- /* Pick up HBA exchange busy condition */ +- if (bf_get(lpfc_wcqe_c_xb, wcqe)) { +- spin_lock_irqsave(&phba->hbalock, iflags); +- pIocbIn->iocb_flag |= LPFC_EXCHANGE_BUSY; +- spin_unlock_irqrestore(&phba->hbalock, iflags); +- } +-} +- +-/** +- * lpfc_sli4_els_wcqe_to_rspiocbq - Get response iocbq from els wcqe ++ * lpfc_sli4_els_preprocess_rspiocbq - Get response iocbq from els wcqe + * @phba: Pointer to HBA context object. + * @irspiocbq: Pointer to work-queue completion queue entry. + * + * This routine handles an ELS work-queue completion event and construct +- * a pseudo response ELS IODBQ from the SLI4 ELS WCQE for the common ++ * a pseudo response ELS IOCBQ from the SLI4 ELS WCQE for the common + * discovery engine to handle. + * + * Return: Pointer to the receive IOCBQ, NULL otherwise. + **/ + static struct lpfc_iocbq * +-lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba, +- struct lpfc_iocbq *irspiocbq) ++lpfc_sli4_els_preprocess_rspiocbq(struct lpfc_hba *phba, ++ struct lpfc_iocbq *irspiocbq) + { + struct lpfc_sli_ring *pring; + struct lpfc_iocbq *cmdiocbq; +@@ -14252,11 +14161,13 @@ lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba, + return NULL; + + wcqe = &irspiocbq->cq_event.cqe.wcqe_cmpl; ++ spin_lock_irqsave(&pring->ring_lock, iflags); + pring->stats.iocb_event++; + /* Look up the ELS command IOCB and create pseudo response IOCB */ + cmdiocbq = lpfc_sli_iocbq_lookup_by_tag(phba, pring, + bf_get(lpfc_wcqe_c_request_tag, wcqe)); + if (unlikely(!cmdiocbq)) { ++ spin_unlock_irqrestore(&pring->ring_lock, iflags); + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, + "0386 ELS complete with no corresponding " + "cmdiocb: 0x%x 0x%x 0x%x 0x%x\n", +@@ -14266,13 +14177,18 @@ lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba, + return NULL; + } + +- spin_lock_irqsave(&pring->ring_lock, iflags); ++ memcpy(&irspiocbq->wqe, &cmdiocbq->wqe, sizeof(union lpfc_wqe128)); ++ memcpy(&irspiocbq->wcqe_cmpl, wcqe, sizeof(*wcqe)); ++ + /* Put the iocb back on the txcmplq */ + lpfc_sli_ringtxcmpl_put(phba, pring, cmdiocbq); + spin_unlock_irqrestore(&pring->ring_lock, iflags); + +- /* Fake the irspiocbq and copy necessary response information */ +- lpfc_sli4_iocb_param_transfer(phba, irspiocbq, cmdiocbq, wcqe); ++ if (bf_get(lpfc_wcqe_c_xb, wcqe)) { ++ spin_lock_irqsave(&phba->hbalock, iflags); ++ irspiocbq->cmd_flag |= LPFC_EXCHANGE_BUSY; ++ spin_unlock_irqrestore(&phba->hbalock, iflags); ++ } + + return irspiocbq; + } +@@ -15073,7 +14989,6 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, + { + struct lpfc_sli_ring *pring = cq->pring; + struct lpfc_iocbq *cmdiocbq; +- struct lpfc_iocbq irspiocbq; + unsigned long iflags; + + /* Check for response status */ +@@ -15099,9 +15014,9 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, + /* Look up the FCP command IOCB and create pseudo response IOCB */ + spin_lock_irqsave(&pring->ring_lock, iflags); + pring->stats.iocb_event++; +- spin_unlock_irqrestore(&pring->ring_lock, iflags); + cmdiocbq = lpfc_sli_iocbq_lookup_by_tag(phba, pring, + bf_get(lpfc_wcqe_c_request_tag, wcqe)); ++ spin_unlock_irqrestore(&pring->ring_lock, iflags); + if (unlikely(!cmdiocbq)) { + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, + "0374 FCP complete with no corresponding " +@@ -15112,39 +15027,31 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS + cmdiocbq->isr_timestamp = cq->isr_timestamp; + #endif +- if (cmdiocbq->iocb_cmpl == NULL) { +- if (cmdiocbq->wqe_cmpl) { +- /* For FCP the flag is cleared in wqe_cmpl */ +- if (!(cmdiocbq->iocb_flag & LPFC_IO_FCP) && +- cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) { +- spin_lock_irqsave(&phba->hbalock, iflags); +- cmdiocbq->iocb_flag &= ~LPFC_DRIVER_ABORTED; +- spin_unlock_irqrestore(&phba->hbalock, iflags); +- } ++ if (bf_get(lpfc_wcqe_c_xb, wcqe)) { ++ spin_lock_irqsave(&phba->hbalock, iflags); ++ cmdiocbq->cmd_flag |= LPFC_EXCHANGE_BUSY; ++ spin_unlock_irqrestore(&phba->hbalock, iflags); ++ } + +- /* Pass the cmd_iocb and the wcqe to the upper layer */ +- (cmdiocbq->wqe_cmpl)(phba, cmdiocbq, wcqe); +- return; ++ if (cmdiocbq->cmd_cmpl) { ++ /* For FCP the flag is cleared in cmd_cmpl */ ++ if (!(cmdiocbq->cmd_flag & LPFC_IO_FCP) && ++ cmdiocbq->cmd_flag & LPFC_DRIVER_ABORTED) { ++ spin_lock_irqsave(&phba->hbalock, iflags); ++ cmdiocbq->cmd_flag &= ~LPFC_DRIVER_ABORTED; ++ spin_unlock_irqrestore(&phba->hbalock, iflags); + } ++ ++ /* Pass the cmd_iocb and the wcqe to the upper layer */ ++ memcpy(&cmdiocbq->wcqe_cmpl, wcqe, ++ sizeof(struct lpfc_wcqe_complete)); ++ cmdiocbq->cmd_cmpl(phba, cmdiocbq, cmdiocbq); ++ } else { + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, + "0375 FCP cmdiocb not callback function " + "iotag: (%d)\n", + bf_get(lpfc_wcqe_c_request_tag, wcqe)); +- return; + } +- +- /* Only SLI4 non-IO commands stil use IOCB */ +- /* Fake the irspiocb and copy necessary response information */ +- lpfc_sli4_iocb_param_transfer(phba, &irspiocbq, cmdiocbq, wcqe); +- +- if (cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) { +- spin_lock_irqsave(&phba->hbalock, iflags); +- cmdiocbq->iocb_flag &= ~LPFC_DRIVER_ABORTED; +- spin_unlock_irqrestore(&phba->hbalock, iflags); +- } +- +- /* Pass the cmd_iocb and the rsp state to the upper layer */ +- (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, &irspiocbq); + } + + /** +@@ -18966,17 +18873,20 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport, + } + + ctiocb->vport = phba->pport; +- ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_rsp_cmpl; ++ ctiocb->cmd_cmpl = lpfc_sli4_seq_abort_rsp_cmpl; + ctiocb->sli4_lxritag = NO_XRI; + ctiocb->sli4_xritag = NO_XRI; + +- if (fctl & FC_FC_EX_CTX) ++ if (fctl & FC_FC_EX_CTX) { + /* Exchange responder sent the abort so we + * own the oxid. + */ ++ ctiocb->abort_bls = LPFC_ABTS_UNSOL_RSP; + xri = oxid; +- else ++ } else { ++ ctiocb->abort_bls = LPFC_ABTS_UNSOL_INT; + xri = rxid; ++ } + lxri = lpfc_sli4_xri_inrange(phba, xri); + if (lxri != NO_XRI) + lpfc_set_rrq_active(phba, ndlp, lxri, +@@ -19299,7 +19209,7 @@ lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *vport, + + /* Free iocb created in lpfc_prep_seq */ + list_for_each_entry_safe(curr_iocb, next_iocb, +- &iocbq->list, list) { ++ &iocbq->list, list) { + list_del_init(&curr_iocb->list); + lpfc_sli_release_iocbq(phba, curr_iocb); + } +@@ -19369,8 +19279,8 @@ lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport, + + iocbq->context2 = pcmd; + iocbq->vport = vport; +- iocbq->iocb_flag &= ~LPFC_FIP_ELS_ID_MASK; +- iocbq->iocb_flag |= LPFC_USE_FCPWQIDX; ++ iocbq->cmd_flag &= ~LPFC_FIP_ELS_ID_MASK; ++ iocbq->cmd_flag |= LPFC_USE_FCPWQIDX; + + /* + * Setup rest of the iocb as though it were a WQE +@@ -19388,7 +19298,7 @@ lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport, + + iocbq->iocb.ulpCommand = CMD_SEND_FRAME; + iocbq->iocb.ulpLe = 1; +- iocbq->iocb_cmpl = lpfc_sli4_mds_loopback_cmpl; ++ iocbq->cmd_cmpl = lpfc_sli4_mds_loopback_cmpl; + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, iocbq, 0); + if (rc == IOCB_ERROR) + goto exit; +@@ -21230,7 +21140,7 @@ lpfc_wqe_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeq, + cmd = bf_get(wqe_cmnd, &wqe->generic.wqe_com); + if (cmd == CMD_XMIT_BLS_RSP64_WQE) + return sglq->sli4_xritag; +- numBdes = pwqeq->rsvd2; ++ numBdes = pwqeq->num_bdes; + if (numBdes) { + /* The addrHigh and addrLow fields within the WQE + * have not been byteswapped yet so there is no +@@ -21331,7 +21241,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp, + uint32_t ret = 0; + + /* NVME_LS and NVME_LS ABTS requests. */ +- if (pwqe->iocb_flag & LPFC_IO_NVME_LS) { ++ if (pwqe->cmd_flag & LPFC_IO_NVME_LS) { + pring = phba->sli4_hba.nvmels_wq->pring; + lpfc_qp_spin_lock_irqsave(&pring->ring_lock, iflags, + qp, wq_access); +@@ -21362,7 +21272,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp, + } + + /* NVME_FCREQ and NVME_ABTS requests */ +- if (pwqe->iocb_flag & (LPFC_IO_NVME | LPFC_IO_FCP | LPFC_IO_CMF)) { ++ if (pwqe->cmd_flag & (LPFC_IO_NVME | LPFC_IO_FCP | LPFC_IO_CMF)) { + /* Get the IO distribution (hba_wqidx) for WQ assignment. */ + wq = qp->io_wq; + pring = wq->pring; +@@ -21384,7 +21294,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp, + } + + /* NVMET requests */ +- if (pwqe->iocb_flag & LPFC_IO_NVMET) { ++ if (pwqe->cmd_flag & LPFC_IO_NVMET) { + /* Get the IO distribution (hba_wqidx) for WQ assignment. */ + wq = qp->io_wq; + pring = wq->pring; +@@ -21450,7 +21360,7 @@ lpfc_sli4_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + return WQE_NORESOURCE; + + /* Indicate the IO is being aborted by the driver. */ +- cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED; ++ cmdiocb->cmd_flag |= LPFC_DRIVER_ABORTED; + + abtswqe = &abtsiocb->wqe; + memset(abtswqe, 0, sizeof(*abtswqe)); +@@ -21469,15 +21379,15 @@ lpfc_sli4_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + + /* ABTS WQE must go to the same WQ as the WQE to be aborted */ + abtsiocb->hba_wqidx = cmdiocb->hba_wqidx; +- abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX; +- if (cmdiocb->iocb_flag & LPFC_IO_FCP) +- abtsiocb->iocb_flag |= LPFC_IO_FCP; +- if (cmdiocb->iocb_flag & LPFC_IO_NVME) +- abtsiocb->iocb_flag |= LPFC_IO_NVME; +- if (cmdiocb->iocb_flag & LPFC_IO_FOF) +- abtsiocb->iocb_flag |= LPFC_IO_FOF; ++ abtsiocb->cmd_flag |= LPFC_USE_FCPWQIDX; ++ if (cmdiocb->cmd_flag & LPFC_IO_FCP) ++ abtsiocb->cmd_flag |= LPFC_IO_FCP; ++ if (cmdiocb->cmd_flag & LPFC_IO_NVME) ++ abtsiocb->cmd_flag |= LPFC_IO_NVME; ++ if (cmdiocb->cmd_flag & LPFC_IO_FOF) ++ abtsiocb->cmd_flag |= LPFC_IO_FOF; + abtsiocb->vport = vport; +- abtsiocb->wqe_cmpl = cmpl; ++ abtsiocb->cmd_cmpl = cmpl; + + lpfc_cmd = container_of(cmdiocb, struct lpfc_io_buf, cur_iocbq); + retval = lpfc_sli4_issue_wqe(phba, lpfc_cmd->hdwq, abtsiocb); +@@ -21488,7 +21398,7 @@ lpfc_sli4_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + xritag, cmdiocb->iotag, abtsiocb->iotag, retval); + + if (retval) { +- cmdiocb->iocb_flag &= ~LPFC_DRIVER_ABORTED; ++ cmdiocb->cmd_flag &= ~LPFC_DRIVER_ABORTED; + __lpfc_sli_release_iocbq(phba, abtsiocb); + } + +@@ -21850,8 +21760,7 @@ void lpfc_release_io_buf(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_ncmd, + + /* MUST zero fields if buffer is reused by another protocol */ + lpfc_ncmd->nvmeCmd = NULL; +- lpfc_ncmd->cur_iocbq.wqe_cmpl = NULL; +- lpfc_ncmd->cur_iocbq.iocb_cmpl = NULL; ++ lpfc_ncmd->cur_iocbq.cmd_cmpl = NULL; + + if (phba->cfg_xpsgl && !phba->nvmet_support && + !list_empty(&lpfc_ncmd->dma_sgl_xtra_list)) +@@ -22035,8 +21944,26 @@ lpfc_get_io_buf_from_multixri_pools(struct lpfc_hba *phba, + + qp = &phba->sli4_hba.hdwq[hwqid]; + lpfc_ncmd = NULL; ++ if (!qp) { ++ lpfc_printf_log(phba, KERN_INFO, ++ LOG_SLI | LOG_NVME_ABTS | LOG_FCP, ++ "5556 NULL qp for hwqid x%x\n", hwqid); ++ return lpfc_ncmd; ++ } + multixri_pool = qp->p_multixri_pool; ++ if (!multixri_pool) { ++ lpfc_printf_log(phba, KERN_INFO, ++ LOG_SLI | LOG_NVME_ABTS | LOG_FCP, ++ "5557 NULL multixri for hwqid x%x\n", hwqid); ++ return lpfc_ncmd; ++ } + pvt_pool = &multixri_pool->pvt_pool; ++ if (!pvt_pool) { ++ lpfc_printf_log(phba, KERN_INFO, ++ LOG_SLI | LOG_NVME_ABTS | LOG_FCP, ++ "5558 NULL pvt_pool for hwqid x%x\n", hwqid); ++ return lpfc_ncmd; ++ } + multixri_pool->io_req_count++; + + /* If pvt_pool is empty, move some XRIs from public to private pool */ +@@ -22112,6 +22039,12 @@ struct lpfc_io_buf *lpfc_get_io_buf(struct lpfc_hba *phba, + + qp = &phba->sli4_hba.hdwq[hwqid]; + lpfc_cmd = NULL; ++ if (!qp) { ++ lpfc_printf_log(phba, KERN_WARNING, ++ LOG_SLI | LOG_NVME_ABTS | LOG_FCP, ++ "5555 NULL qp for hwqid x%x\n", hwqid); ++ return lpfc_cmd; ++ } + + if (phba->cfg_xri_rebalancing) + lpfc_cmd = lpfc_get_io_buf_from_multixri_pools( +diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h +index 5161ccacea3e9..06682ad8bbe15 100644 +--- a/drivers/scsi/lpfc/lpfc_sli.h ++++ b/drivers/scsi/lpfc/lpfc_sli.h +@@ -35,7 +35,7 @@ typedef enum _lpfc_ctx_cmd { + LPFC_CTX_HOST + } lpfc_ctx_cmd; + +-union lpfc_vmid_iocb_tag { ++union lpfc_vmid_tag { + uint32_t app_id; + uint8_t cs_ctl_vmid; + struct lpfc_vmid_context *vmid_context; /* UVEM context information */ +@@ -69,16 +69,18 @@ struct lpfc_iocbq { + uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ + uint16_t hba_wqidx; /* index to HBA work queue */ + struct lpfc_cq_event cq_event; +- struct lpfc_wcqe_complete wcqe_cmpl; /* WQE cmpl */ + uint64_t isr_timestamp; + + union lpfc_wqe128 wqe; /* SLI-4 */ + IOCB_t iocb; /* SLI-3 */ ++ struct lpfc_wcqe_complete wcqe_cmpl; /* WQE cmpl */ ++ ++ uint8_t num_bdes; ++ uint8_t abort_bls; /* ABTS by initiator or responder */ + +- uint8_t rsvd2; + uint8_t priority; /* OAS priority */ + uint8_t retry; /* retry counter for IOCB cmd - if needed */ +- uint32_t iocb_flag; ++ u32 cmd_flag; + #define LPFC_IO_LIBDFC 1 /* libdfc iocb */ + #define LPFC_IO_WAKE 2 /* Synchronous I/O completed */ + #define LPFC_IO_WAKE_TMO LPFC_IO_WAKE /* Synchronous I/O timed out */ +@@ -123,15 +125,13 @@ struct lpfc_iocbq { + struct lpfc_node_rrq *rrq; + } context_un; + +- union lpfc_vmid_iocb_tag vmid_tag; +- void (*fabric_iocb_cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, +- struct lpfc_iocbq *); +- void (*wait_iocb_cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, +- struct lpfc_iocbq *); +- void (*iocb_cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, +- struct lpfc_iocbq *); +- void (*wqe_cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, +- struct lpfc_wcqe_complete *); ++ union lpfc_vmid_tag vmid_tag; ++ void (*fabric_cmd_cmpl)(struct lpfc_hba *phba, struct lpfc_iocbq *cmd, ++ struct lpfc_iocbq *rsp); ++ void (*wait_cmd_cmpl)(struct lpfc_hba *phba, struct lpfc_iocbq *cmd, ++ struct lpfc_iocbq *rsp); ++ void (*cmd_cmpl)(struct lpfc_hba *phba, struct lpfc_iocbq *cmd, ++ struct lpfc_iocbq *rsp); + }; + + #define SLI_IOCB_RET_IOCB 1 /* Return IOCB if cmd ring full */ +diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h +index 99c5d1e4da5ef..5962cf508842f 100644 +--- a/drivers/scsi/lpfc/lpfc_sli4.h ++++ b/drivers/scsi/lpfc/lpfc_sli4.h +@@ -1116,6 +1116,8 @@ void lpfc_sli4_fcf_redisc_event_proc(struct lpfc_hba *); + int lpfc_sli4_resume_rpi(struct lpfc_nodelist *, + void (*)(struct lpfc_hba *, LPFC_MBOXQ_t *), void *); + void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *phba); ++void lpfc_sli4_nvme_pci_offline_aborted(struct lpfc_hba *phba, ++ struct lpfc_io_buf *lpfc_ncmd); + void lpfc_sli4_nvme_xri_aborted(struct lpfc_hba *phba, + struct sli4_wcqe_xri_aborted *axri, + struct lpfc_io_buf *lpfc_ncmd); +diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c +index e6dc0b495a829..a117d11f2b078 100644 +--- a/drivers/scsi/qedi/qedi_main.c ++++ b/drivers/scsi/qedi/qedi_main.c +@@ -2417,9 +2417,12 @@ static void __qedi_remove(struct pci_dev *pdev, int mode) + int rval; + u16 retry = 10; + +- if (mode == QEDI_MODE_NORMAL || mode == QEDI_MODE_SHUTDOWN) { +- iscsi_host_remove(qedi->shost); ++ if (mode == QEDI_MODE_NORMAL) ++ iscsi_host_remove(qedi->shost, false); ++ else if (mode == QEDI_MODE_SHUTDOWN) ++ iscsi_host_remove(qedi->shost, true); + ++ if (mode == QEDI_MODE_NORMAL || mode == QEDI_MODE_SHUTDOWN) { + if (qedi->tmf_thread) { + flush_workqueue(qedi->tmf_thread); + destroy_workqueue(qedi->tmf_thread); +@@ -2796,7 +2799,7 @@ remove_host: + #ifdef CONFIG_DEBUG_FS + qedi_dbg_host_exit(&qedi->dbg_ctx); + #endif +- iscsi_host_remove(qedi->shost); ++ iscsi_host_remove(qedi->shost, false); + stop_iscsi_func: + qedi_ops->stop(qedi->cdev); + stop_slowpath: +diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c +index d3534e7f2d214..a302ed8b610fb 100644 +--- a/drivers/scsi/qla2xxx/qla_attr.c ++++ b/drivers/scsi/qla2xxx/qla_attr.c +@@ -2705,17 +2705,24 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport) + if (!fcport) + return; + +- /* Now that the rport has been deleted, set the fcport state to +- FCS_DEVICE_DEAD */ +- qla2x00_set_fcport_state(fcport, FCS_DEVICE_DEAD); ++ ++ /* ++ * Now that the rport has been deleted, set the fcport state to ++ * FCS_DEVICE_DEAD, if the fcport is still lost. ++ */ ++ if (fcport->scan_state != QLA_FCPORT_FOUND) ++ qla2x00_set_fcport_state(fcport, FCS_DEVICE_DEAD); + + /* + * Transport has effectively 'deleted' the rport, clear + * all local references. + */ + spin_lock_irqsave(host->host_lock, flags); +- fcport->rport = fcport->drport = NULL; +- *((fc_port_t **)rport->dd_data) = NULL; ++ /* Confirm port has not reappeared before clearing pointers. */ ++ if (rport->port_state != FC_PORTSTATE_ONLINE) { ++ fcport->rport = fcport->drport = NULL; ++ *((fc_port_t **)rport->dd_data) = NULL; ++ } + spin_unlock_irqrestore(host->host_lock, flags); + + if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags)) +@@ -2748,14 +2755,22 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) + /* + * At this point all fcport's software-states are cleared. Perform any + * final cleanup of firmware resources (PCBs and XCBs). ++ * ++ * Attempt to cleanup only lost devices. + */ + if (fcport->loop_id != FC_NO_LOOP_ID) { +- if (IS_FWI2_CAPABLE(fcport->vha->hw)) { ++ if (IS_FWI2_CAPABLE(fcport->vha->hw) && ++ fcport->scan_state != QLA_FCPORT_FOUND) { + if (fcport->loop_id != FC_NO_LOOP_ID) + fcport->logout_on_delete = 1; + +- qlt_schedule_sess_for_deletion(fcport); +- } else { ++ if (!EDIF_NEGOTIATION_PENDING(fcport)) { ++ ql_dbg(ql_dbg_disc, fcport->vha, 0x911e, ++ "%s %d schedule session deletion\n", __func__, ++ __LINE__); ++ qlt_schedule_sess_for_deletion(fcport); ++ } ++ } else if (!IS_FWI2_CAPABLE(fcport->vha->hw)) { + qla2x00_port_logout(fcport->vha, fcport); + } + } +diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c +index c636165be52be..3650f16cab6cf 100644 +--- a/drivers/scsi/qla2xxx/qla_bsg.c ++++ b/drivers/scsi/qla2xxx/qla_bsg.c +@@ -2972,6 +2972,13 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job) + + ql_log(ql_log_info, vha, 0x708b, "%s CMD timeout. bsg ptr %p.\n", + __func__, bsg_job); ++ ++ if (qla2x00_isp_reg_stat(ha)) { ++ ql_log(ql_log_info, vha, 0x9007, ++ "PCI/Register disconnect.\n"); ++ qla_pci_set_eeh_busy(vha); ++ } ++ + /* find the bsg job from the active list of commands */ + spin_lock_irqsave(&ha->hardware_lock, flags); + for (que = 0; que < ha->max_req_queues; que++) { +@@ -2989,7 +2996,8 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job) + sp->u.bsg_job == bsg_job) { + req->outstanding_cmds[cnt] = NULL; + spin_unlock_irqrestore(&ha->hardware_lock, flags); +- if (ha->isp_ops->abort_command(sp)) { ++ ++ if (!ha->flags.eeh_busy && ha->isp_ops->abort_command(sp)) { + ql_log(ql_log_warn, vha, 0x7089, + "mbx abort_command failed.\n"); + bsg_reply->result = -EIO; +diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h +index 303ad60d1d49d..51c7ce5f97923 100644 +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -2158,6 +2158,11 @@ typedef struct { + #define CS_IOCB_ERROR 0x31 /* Generic error for IOCB request + failure */ + #define CS_REJECT_RECEIVED 0x4E /* Reject received */ ++#define CS_EDIF_AUTH_ERROR 0x63 /* decrypt error */ ++#define CS_EDIF_PAD_LEN_ERROR 0x65 /* pad > frame size, not 4byte align */ ++#define CS_EDIF_INV_REQ 0x66 /* invalid request */ ++#define CS_EDIF_SPI_ERROR 0x67 /* rx frame unable to locate sa */ ++#define CS_EDIF_HDR_ERROR 0x69 /* data frame != expected len */ + #define CS_BAD_PAYLOAD 0x80 /* Driver defined */ + #define CS_UNKNOWN 0x81 /* Driver defined */ + #define CS_RETRY 0x82 /* Driver defined */ +@@ -3201,6 +3206,8 @@ struct ct_sns_rsp { + #define GFF_NVME_OFFSET 23 /* type = 28h */ + struct { + uint8_t fc4_features[128]; ++#define FC4_FF_TARGET BIT_0 ++#define FC4_FF_INITIATOR BIT_1 + } gff_id; + struct { + uint8_t reserved; +@@ -3972,6 +3979,7 @@ struct qla_hw_data { + /* SRB cache. */ + #define SRB_MIN_REQ 128 + mempool_t *srb_mempool; ++ u8 port_name[WWN_SIZE]; + + volatile struct { + uint32_t mbox_int :1; +@@ -4037,6 +4045,9 @@ struct qla_hw_data { + uint32_t n2n_fw_acc_sec:1; + uint32_t plogi_template_valid:1; + uint32_t port_isolated:1; ++ uint32_t eeh_flush:2; ++#define EEH_FLUSH_RDY 1 ++#define EEH_FLUSH_DONE 2 + } flags; + + uint16_t max_exchg; +@@ -4071,6 +4082,7 @@ struct qla_hw_data { + uint32_t rsp_que_len; + uint32_t req_que_off; + uint32_t rsp_que_off; ++ unsigned long eeh_jif; + + /* Multi queue data structs */ + device_reg_t *mqiobase; +@@ -4253,8 +4265,8 @@ struct qla_hw_data { + #define IS_OEM_001(ha) ((ha)->device_type & DT_OEM_001) + #define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS) + #define IS_CT6_SUPPORTED(ha) ((ha)->device_type & DT_CT6_SUPPORTED) +-#define IS_MQUE_CAPABLE(ha) ((ha)->mqenable || IS_QLA83XX(ha) || \ +- IS_QLA27XX(ha) || IS_QLA28XX(ha)) ++#define IS_MQUE_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \ ++ IS_QLA28XX(ha)) + #define IS_BIDI_CAPABLE(ha) \ + (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) + /* Bit 21 of fw_attributes decides the MCTP capabilities */ +diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c +index e40b9cc382146..8e9237434e8b1 100644 +--- a/drivers/scsi/qla2xxx/qla_edif.c ++++ b/drivers/scsi/qla2xxx/qla_edif.c +@@ -218,7 +218,7 @@ fc_port_t *fcport) + "%s edif not enabled\n", __func__); + goto done; + } +- if (vha->e_dbell.db_flags != EDB_ACTIVE) { ++ if (DBELL_INACTIVE(vha)) { + ql_dbg(ql_dbg_edif, vha, 0x09102, + "%s doorbell not enabled\n", __func__); + goto done; +@@ -482,15 +482,17 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app_vid=%x app_start_flags %x\n", + __func__, appstart.app_info.app_vid, appstart.app_start_flags); + +- if (vha->e_dbell.db_flags != EDB_ACTIVE) { ++ if (DBELL_INACTIVE(vha)) { + /* mark doorbell as active since an app is now present */ +- vha->e_dbell.db_flags = EDB_ACTIVE; ++ vha->e_dbell.db_flags |= EDB_ACTIVE; + } else { +- ql_dbg(ql_dbg_edif, vha, 0x911e, "%s doorbell already active\n", +- __func__); ++ goto out; + } + + if (N2N_TOPO(vha->hw)) { ++ list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) ++ fcport->n2n_link_reset_cnt = 0; ++ + if (vha->hw->flags.n2n_fw_acc_sec) + set_bit(N2N_LINK_RESET, &vha->dpc_flags); + else +@@ -517,19 +519,32 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + if (atomic_read(&vha->loop_state) == LOOP_DOWN) + break; + +- fcport->edif.app_started = 1; + fcport->login_retry = vha->hw->login_retry_count; + +- /* no activity */ + fcport->edif.app_stop = 0; ++ fcport->edif.app_sess_online = 0; ++ fcport->edif.app_started = 1; ++ ++ if (fcport->scan_state != QLA_FCPORT_FOUND) ++ continue; ++ ++ if (fcport->port_type == FCT_UNKNOWN && ++ !fcport->fc4_features) ++ rval = qla24xx_async_gffid(vha, fcport, true); ++ ++ if (!rval && !(fcport->fc4_features & FC4_FF_TARGET || ++ fcport->port_type & (FCT_TARGET|FCT_NVME_TARGET))) ++ continue; ++ ++ rval = 0; + + ql_dbg(ql_dbg_edif, vha, 0x911e, + "%s wwpn %8phC calling qla_edif_reset_auth_wait\n", + __func__, fcport->port_name); +- fcport->edif.app_sess_online = 0; + qlt_schedule_sess_for_deletion(fcport); + qla_edif_sa_ctl_init(vha, fcport); + } ++ set_bit(RELOGIN_NEEDED, &vha->dpc_flags); + } + + if (vha->pur_cinfo.enode_flags != ENODE_ACTIVE) { +@@ -540,6 +555,7 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + __func__); + } + ++out: + appreply.host_support_edif = vha->hw->flags.edif_enabled; + appreply.edif_enode_active = vha->pur_cinfo.enode_flags; + appreply.edif_edb_active = vha->e_dbell.db_flags; +@@ -884,6 +900,20 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + app_reply->ports[pcnt].rekey_count = + fcport->edif.rekey_cnt; + ++ if (fcport->scan_state != QLA_FCPORT_FOUND) ++ continue; ++ ++ if (fcport->port_type == FCT_UNKNOWN && !fcport->fc4_features) ++ rval = qla24xx_async_gffid(vha, fcport, true); ++ ++ if (!rval && ++ !(fcport->fc4_features & FC4_FF_TARGET || ++ fcport->port_type & ++ (FCT_TARGET | FCT_NVME_TARGET))) ++ continue; ++ ++ rval = 0; ++ + app_reply->ports[pcnt].remote_type = + VND_CMD_RTYPE_UNKNOWN; + if (fcport->port_type & (FCT_NVME_TARGET | FCT_TARGET)) +@@ -1248,6 +1278,8 @@ qla24xx_check_sadb_avail_slot(struct bsg_job *bsg_job, fc_port_t *fcport, + + #define QLA_SA_UPDATE_FLAGS_RX_KEY 0x0 + #define QLA_SA_UPDATE_FLAGS_TX_KEY 0x2 ++#define EDIF_MSLEEP_INTERVAL 100 ++#define EDIF_RETRY_COUNT 50 + + int + qla24xx_sadb_update(struct bsg_job *bsg_job) +@@ -1260,7 +1292,7 @@ qla24xx_sadb_update(struct bsg_job *bsg_job) + struct edif_list_entry *edif_entry = NULL; + int found = 0; + int rval = 0; +- int result = 0; ++ int result = 0, cnt; + struct qla_sa_update_frame sa_frame; + struct srb_iocb *iocb_cmd; + port_id_t portid; +@@ -1280,7 +1312,7 @@ qla24xx_sadb_update(struct bsg_job *bsg_job) + goto done; + } + +- if (vha->e_dbell.db_flags != EDB_ACTIVE) { ++ if (DBELL_INACTIVE(vha)) { + ql_log(ql_log_warn, vha, 0x70a1, "App not started\n"); + rval = -EIO; + SET_DID_STATUS(bsg_reply->result, DID_ERROR); +@@ -1501,11 +1533,23 @@ force_rx_delete: + sp->done = qla2x00_bsg_job_done; + iocb_cmd = &sp->u.iocb_cmd; + iocb_cmd->u.sa_update.sa_frame = sa_frame; +- ++ cnt = 0; ++retry: + rval = qla2x00_start_sp(sp); +- if (rval != QLA_SUCCESS) { ++ switch (rval) { ++ case QLA_SUCCESS: ++ break; ++ case EAGAIN: ++ msleep(EDIF_MSLEEP_INTERVAL); ++ cnt++; ++ if (cnt < EDIF_RETRY_COUNT) ++ goto retry; ++ ++ fallthrough; ++ default: + ql_log(ql_dbg_edif, vha, 0x70e3, +- "qla2x00_start_sp failed=%d.\n", rval); ++ "%s qla2x00_start_sp failed=%d.\n", ++ __func__, rval); + + qla2x00_rel_sp(sp); + rval = -EIO; +@@ -1787,7 +1831,7 @@ qla_els_reject_iocb(scsi_qla_host_t *vha, struct qla_qpair *qp, + void + qla_edb_init(scsi_qla_host_t *vha) + { +- if (vha->e_dbell.db_flags == EDB_ACTIVE) { ++ if (DBELL_ACTIVE(vha)) { + /* list already init'd - error */ + ql_dbg(ql_dbg_edif, vha, 0x09102, + "edif db already initialized, cannot reinit\n"); +@@ -1830,7 +1874,7 @@ static void qla_edb_clear(scsi_qla_host_t *vha, port_id_t portid) + port_id_t sid; + LIST_HEAD(edb_list); + +- if (vha->e_dbell.db_flags != EDB_ACTIVE) { ++ if (DBELL_INACTIVE(vha)) { + /* doorbell list not enabled */ + ql_dbg(ql_dbg_edif, vha, 0x09102, + "%s doorbell not enabled\n", __func__); +@@ -1882,7 +1926,7 @@ qla_edb_stop(scsi_qla_host_t *vha) + unsigned long flags; + struct edb_node *node, *q; + +- if (vha->e_dbell.db_flags != EDB_ACTIVE) { ++ if (DBELL_INACTIVE(vha)) { + /* doorbell list not enabled */ + ql_dbg(ql_dbg_edif, vha, 0x09102, + "%s doorbell not enabled\n", __func__); +@@ -1933,7 +1977,7 @@ qla_edb_node_add(scsi_qla_host_t *vha, struct edb_node *ptr) + { + unsigned long flags; + +- if (vha->e_dbell.db_flags != EDB_ACTIVE) { ++ if (DBELL_INACTIVE(vha)) { + /* doorbell list not enabled */ + ql_dbg(ql_dbg_edif, vha, 0x09102, + "%s doorbell not enabled\n", __func__); +@@ -1964,7 +2008,7 @@ qla_edb_eventcreate(scsi_qla_host_t *vha, uint32_t dbtype, + return; + } + +- if (vha->e_dbell.db_flags != EDB_ACTIVE) { ++ if (DBELL_INACTIVE(vha)) { + if (fcport) + fcport->edif.auth_state = dbtype; + /* doorbell list not enabled */ +@@ -2059,7 +2103,7 @@ qla_edif_timer(scsi_qla_host_t *vha) + struct qla_hw_data *ha = vha->hw; + + if (!vha->vp_idx && N2N_TOPO(ha) && ha->flags.n2n_fw_acc_sec) { +- if (vha->e_dbell.db_flags != EDB_ACTIVE && ++ if (DBELL_INACTIVE(vha) && + ha->edif_post_stop_cnt_down) { + ha->edif_post_stop_cnt_down--; + +@@ -2097,7 +2141,7 @@ edif_doorbell_show(struct device *dev, struct device_attribute *attr, + sz = 256; + + /* stop new threads from waiting if we're not init'd */ +- if (vha->e_dbell.db_flags != EDB_ACTIVE) { ++ if (DBELL_INACTIVE(vha)) { + ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x09122, + "%s error - edif db not enabled\n", __func__); + return 0; +@@ -2161,6 +2205,7 @@ edif_doorbell_show(struct device *dev, struct device_attribute *attr, + + static void qla_noop_sp_done(srb_t *sp, int res) + { ++ sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); + /* ref: INIT */ + kref_put(&sp->cmd_kref, qla2x00_sp_release); + } +@@ -2185,7 +2230,8 @@ qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha, struct qla_work_evt *e) + if (!sa_ctl) { + ql_dbg(ql_dbg_edif, vha, 0x70e6, + "sa_ctl allocation failed\n"); +- return -ENOMEM; ++ rval = -ENOMEM; ++ goto done; + } + + fcport = sa_ctl->fcport; +@@ -2195,7 +2241,8 @@ qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha, struct qla_work_evt *e) + if (!sp) { + ql_dbg(ql_dbg_edif, vha, 0x70e6, + "SRB allocation failed\n"); +- return -ENOMEM; ++ rval = -ENOMEM; ++ goto done; + } + + fcport->flags |= FCF_ASYNC_SENT; +@@ -2224,9 +2271,16 @@ qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha, struct qla_work_evt *e) + + rval = qla2x00_start_sp(sp); + +- if (rval != QLA_SUCCESS) +- rval = QLA_FUNCTION_FAILED; ++ if (rval != QLA_SUCCESS) { ++ goto done_free_sp; ++ } + ++ return rval; ++done_free_sp: ++ kref_put(&sp->cmd_kref, qla2x00_sp_release); ++ fcport->flags &= ~FCF_ASYNC_SENT; ++done: ++ fcport->flags &= ~FCF_ASYNC_ACTIVE; + return rval; + } + +@@ -2443,8 +2497,7 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp) + + fcport = qla2x00_find_fcport_by_pid(host, &purex->pur_info.pur_sid); + +- if (host->e_dbell.db_flags != EDB_ACTIVE || +- (fcport && EDIF_SESSION_DOWN(fcport))) { ++ if (DBELL_INACTIVE(vha)) { + ql_dbg(ql_dbg_edif, host, 0x0910c, "%s e_dbell.db_flags =%x %06x\n", + __func__, host->e_dbell.db_flags, + fcport ? fcport->d_id.b24 : 0); +@@ -2454,6 +2507,22 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp) + return; + } + ++ if (fcport && EDIF_SESSION_DOWN(fcport)) { ++ ql_dbg(ql_dbg_edif, host, 0x13b6, ++ "%s terminate exchange. Send logo to 0x%x\n", ++ __func__, a.did.b24); ++ ++ a.tx_byte_count = a.tx_len = 0; ++ a.tx_addr = 0; ++ a.control_flags = EPD_RX_XCHG; /* EPD_RX_XCHG = terminate cmd */ ++ qla_els_reject_iocb(host, (*rsp)->qpair, &a); ++ qla_enode_free(host, ptr); ++ /* send logo to let remote port knows to tear down session */ ++ fcport->send_els_logo = 1; ++ qlt_schedule_sess_for_deletion(fcport); ++ return; ++ } ++ + /* add the local enode to the list */ + qla_enode_add(host, ptr); + +@@ -3346,7 +3415,7 @@ int qla_edif_process_els(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + fc_port_t *fcport = NULL; + struct qla_hw_data *ha = vha->hw; + srb_t *sp; +- int rval = (DID_ERROR << 16); ++ int rval = (DID_ERROR << 16), cnt; + port_id_t d_id; + struct qla_bsg_auth_els_request *p = + (struct qla_bsg_auth_els_request *)bsg_job->request; +@@ -3368,7 +3437,7 @@ int qla_edif_process_els(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + if (qla_bsg_check(vha, bsg_job, fcport)) + return 0; + +- if (fcport->loop_id == FC_NO_LOOP_ID) { ++ if (EDIF_SESS_DELETE(fcport)) { + ql_dbg(ql_dbg_edif, vha, 0x910d, + "%s ELS code %x, no loop id.\n", __func__, + bsg_request->rqst_data.r_els.els_code); +@@ -3437,17 +3506,26 @@ int qla_edif_process_els(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + sp->free = qla2x00_bsg_sp_free; + sp->done = qla2x00_bsg_job_done; + ++ cnt = 0; ++retry: + rval = qla2x00_start_sp(sp); +- +- ql_dbg(ql_dbg_edif, vha, 0x700a, +- "%s %s %8phN xchg %x ctlflag %x hdl %x reqlen %xh bsg ptr %p\n", +- __func__, sc_to_str(p->e.sub_cmd), fcport->port_name, +- p->e.extra_rx_xchg_address, p->e.extra_control_flags, +- sp->handle, sp->remap.req.len, bsg_job); +- +- if (rval != QLA_SUCCESS) { ++ switch (rval) { ++ case QLA_SUCCESS: ++ ql_dbg(ql_dbg_edif, vha, 0x700a, ++ "%s %s %8phN xchg %x ctlflag %x hdl %x reqlen %xh bsg ptr %p\n", ++ __func__, sc_to_str(p->e.sub_cmd), fcport->port_name, ++ p->e.extra_rx_xchg_address, p->e.extra_control_flags, ++ sp->handle, sp->remap.req.len, bsg_job); ++ break; ++ case EAGAIN: ++ msleep(EDIF_MSLEEP_INTERVAL); ++ cnt++; ++ if (cnt < EDIF_RETRY_COUNT) ++ goto retry; ++ fallthrough; ++ default: + ql_log(ql_log_warn, vha, 0x700e, +- "qla2x00_start_sp failed = %d\n", rval); ++ "%s qla2x00_start_sp failed = %d\n", __func__, rval); + SET_DID_STATUS(bsg_reply->result, DID_IMM_RETRY); + rval = -EIO; + goto done_free_remap_rsp; +@@ -3469,7 +3547,7 @@ done: + + void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess) + { +- if (sess->edif.app_sess_online && vha->e_dbell.db_flags & EDB_ACTIVE) { ++ if (sess->edif.app_sess_online && DBELL_ACTIVE(vha)) { + ql_dbg(ql_dbg_disc, vha, 0xf09c, + "%s: sess %8phN send port_offline event\n", + __func__, sess->port_name); +diff --git a/drivers/scsi/qla2xxx/qla_edif.h b/drivers/scsi/qla2xxx/qla_edif.h +index 32800bfb32a38..b9cedf6defd94 100644 +--- a/drivers/scsi/qla2xxx/qla_edif.h ++++ b/drivers/scsi/qla2xxx/qla_edif.h +@@ -41,9 +41,12 @@ struct pur_core { + }; + + enum db_flags_t { +- EDB_ACTIVE = 0x1, ++ EDB_ACTIVE = BIT_0, + }; + ++#define DBELL_ACTIVE(_v) (_v->e_dbell.db_flags & EDB_ACTIVE) ++#define DBELL_INACTIVE(_v) (!(_v->e_dbell.db_flags & EDB_ACTIVE)) ++ + struct edif_dbell { + enum db_flags_t db_flags; + spinlock_t db_lock; +@@ -133,4 +136,12 @@ struct enode { + _s->disc_state == DSC_DELETED || \ + !_s->edif.app_sess_online)) + ++#define EDIF_NEGOTIATION_PENDING(_fcport) \ ++ (DBELL_ACTIVE(_fcport->vha) && \ ++ (_fcport->disc_state == DSC_LOGIN_AUTH_PEND)) ++ ++#define EDIF_SESS_DELETE(_s) \ ++ (qla_ini_mode_enabled(_s->vha) && (_s->disc_state == DSC_DELETE_PEND || \ ++ _s->disc_state == DSC_DELETED)) ++ + #endif /* __QLA_EDIF_H */ +diff --git a/drivers/scsi/qla2xxx/qla_edif_bsg.h b/drivers/scsi/qla2xxx/qla_edif_bsg.h +index 53026d82ebffe..af9f1ffb1e4a6 100644 +--- a/drivers/scsi/qla2xxx/qla_edif_bsg.h ++++ b/drivers/scsi/qla2xxx/qla_edif_bsg.h +@@ -217,4 +217,6 @@ struct auth_complete_cmd { + + #define RX_DELAY_DELETE_TIMEOUT 20 + ++#define FCH_EVT_VENDOR_UNIQUE_VPORT_DOWN 1 ++ + #endif /* QLA_EDIF_BSG_H */ +diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h +index 073d06e88c589..6faf7533958f1 100644 +--- a/drivers/scsi/qla2xxx/qla_fw.h ++++ b/drivers/scsi/qla2xxx/qla_fw.h +@@ -807,7 +807,7 @@ struct els_entry_24xx { + #define EPD_ELS_COMMAND (0 << 13) + #define EPD_ELS_ACC (1 << 13) + #define EPD_ELS_RJT (2 << 13) +-#define EPD_RX_XCHG (3 << 13) ++#define EPD_RX_XCHG (3 << 13) /* terminate exchange */ + #define ECF_CLR_PASSTHRU_PEND BIT_12 + #define ECF_INCL_FRAME_HDR BIT_11 + #define ECF_SEC_LOGIN BIT_3 +diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h +index 83912787fa2e0..2a6d613a76cf3 100644 +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -334,6 +334,7 @@ extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *); + extern int qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha, + struct qla_work_evt *e); + void qla2x00_sp_release(struct kref *kref); ++void qla2x00_els_dcmd2_iocb_timeout(void *data); + + /* + * Global Function Prototypes in qla_mbx.c source file. +@@ -432,7 +433,8 @@ extern int + qla2x00_get_resource_cnts(scsi_qla_host_t *); + + extern int +-qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map); ++qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map, ++ u8 *num_entries); + + extern int + qla2x00_get_link_status(scsi_qla_host_t *, uint16_t, struct link_statistics *, +@@ -722,7 +724,7 @@ int qla24xx_async_gpsc(scsi_qla_host_t *, fc_port_t *); + void qla24xx_handle_gpsc_event(scsi_qla_host_t *, struct event_arg *); + int qla2x00_mgmt_svr_login(scsi_qla_host_t *); + void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea); +-int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport); ++int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport, bool); + int qla24xx_async_gpnft(scsi_qla_host_t *, u8, srb_t *); + void qla24xx_async_gpnft_done(scsi_qla_host_t *, srb_t *); + void qla24xx_async_gnnft_done(scsi_qla_host_t *, srb_t *); +diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c +index da7080c4bd008..d3742a83d2fd7 100644 +--- a/drivers/scsi/qla2xxx/qla_gs.c ++++ b/drivers/scsi/qla2xxx/qla_gs.c +@@ -1595,7 +1595,6 @@ qla2x00_hba_attributes(scsi_qla_host_t *vha, void *entries, + unsigned int callopt) + { + struct qla_hw_data *ha = vha->hw; +- struct init_cb_24xx *icb24 = (void *)ha->init_cb; + struct new_utsname *p_sysid = utsname(); + struct ct_fdmi_hba_attr *eiter; + uint16_t alen; +@@ -1757,8 +1756,8 @@ qla2x00_hba_attributes(scsi_qla_host_t *vha, void *entries, + /* MAX CT Payload Length */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH); +- eiter->a.max_ct_len = cpu_to_be32(le16_to_cpu(IS_FWI2_CAPABLE(ha) ? +- icb24->frame_payload_size : ha->init_cb->frame_payload_size)); ++ eiter->a.max_ct_len = cpu_to_be32(ha->frame_payload_size >> 2); ++ + alen = sizeof(eiter->a.max_ct_len); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); +@@ -1850,7 +1849,6 @@ qla2x00_port_attributes(scsi_qla_host_t *vha, void *entries, + unsigned int callopt) + { + struct qla_hw_data *ha = vha->hw; +- struct init_cb_24xx *icb24 = (void *)ha->init_cb; + struct new_utsname *p_sysid = utsname(); + char *hostname = p_sysid ? + p_sysid->nodename : fc_host_system_hostname(vha->host); +@@ -1902,8 +1900,7 @@ qla2x00_port_attributes(scsi_qla_host_t *vha, void *entries, + /* Max frame size. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); +- eiter->a.max_frame_size = cpu_to_be32(le16_to_cpu(IS_FWI2_CAPABLE(ha) ? +- icb24->frame_payload_size : ha->init_cb->frame_payload_size)); ++ eiter->a.max_frame_size = cpu_to_be32(ha->frame_payload_size); + alen = sizeof(eiter->a.max_frame_size); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); +@@ -3279,19 +3276,12 @@ done: + return rval; + } + +-void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea) +-{ +- fc_port_t *fcport = ea->fcport; +- +- qla24xx_post_gnl_work(vha, fcport); +-} + + void qla24xx_async_gffid_sp_done(srb_t *sp, int res) + { + struct scsi_qla_host *vha = sp->vha; + fc_port_t *fcport = sp->fcport; + struct ct_sns_rsp *ct_rsp; +- struct event_arg ea; + uint8_t fc4_scsi_feat; + uint8_t fc4_nvme_feat; + +@@ -3299,10 +3289,10 @@ void qla24xx_async_gffid_sp_done(srb_t *sp, int res) + "Async done-%s res %x ID %x. %8phC\n", + sp->name, res, fcport->d_id.b24, fcport->port_name); + +- fcport->flags &= ~FCF_ASYNC_SENT; +- ct_rsp = &fcport->ct_desc.ct_sns->p.rsp; ++ ct_rsp = sp->u.iocb_cmd.u.ctarg.rsp; + fc4_scsi_feat = ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET]; + fc4_nvme_feat = ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET]; ++ sp->rc = res; + + /* + * FC-GS-7, 5.2.3.12 FC-4 Features - format +@@ -3323,24 +3313,42 @@ void qla24xx_async_gffid_sp_done(srb_t *sp, int res) + } + } + +- memset(&ea, 0, sizeof(ea)); +- ea.sp = sp; +- ea.fcport = sp->fcport; +- ea.rc = res; ++ if (sp->flags & SRB_WAKEUP_ON_COMP) { ++ complete(sp->comp); ++ } else { ++ if (sp->u.iocb_cmd.u.ctarg.req) { ++ dma_free_coherent(&vha->hw->pdev->dev, ++ sp->u.iocb_cmd.u.ctarg.req_allocated_size, ++ sp->u.iocb_cmd.u.ctarg.req, ++ sp->u.iocb_cmd.u.ctarg.req_dma); ++ sp->u.iocb_cmd.u.ctarg.req = NULL; ++ } + +- qla24xx_handle_gffid_event(vha, &ea); +- /* ref: INIT */ +- kref_put(&sp->cmd_kref, qla2x00_sp_release); ++ if (sp->u.iocb_cmd.u.ctarg.rsp) { ++ dma_free_coherent(&vha->hw->pdev->dev, ++ sp->u.iocb_cmd.u.ctarg.rsp_allocated_size, ++ sp->u.iocb_cmd.u.ctarg.rsp, ++ sp->u.iocb_cmd.u.ctarg.rsp_dma); ++ sp->u.iocb_cmd.u.ctarg.rsp = NULL; ++ } ++ ++ /* ref: INIT */ ++ kref_put(&sp->cmd_kref, qla2x00_sp_release); ++ /* we should not be here */ ++ dump_stack(); ++ } + } + + /* Get FC4 Feature with Nport ID. */ +-int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport) ++int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport, bool wait) + { + int rval = QLA_FUNCTION_FAILED; + struct ct_sns_req *ct_req; + srb_t *sp; ++ DECLARE_COMPLETION_ONSTACK(comp); + +- if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT)) ++ /* this routine does not have handling for no wait */ ++ if (!vha->flags.online || !wait) + return rval; + + /* ref: INIT */ +@@ -3348,43 +3356,86 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport) + if (!sp) + return rval; + +- fcport->flags |= FCF_ASYNC_SENT; + sp->type = SRB_CT_PTHRU_CMD; + sp->name = "gffid"; + sp->gen1 = fcport->rscn_gen; + sp->gen2 = fcport->login_gen; + qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2, + qla24xx_async_gffid_sp_done); ++ sp->comp = ∁ ++ sp->u.iocb_cmd.timeout = qla2x00_els_dcmd2_iocb_timeout; ++ ++ if (wait) ++ sp->flags = SRB_WAKEUP_ON_COMP; ++ ++ sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt); ++ sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev, ++ sp->u.iocb_cmd.u.ctarg.req_allocated_size, ++ &sp->u.iocb_cmd.u.ctarg.req_dma, ++ GFP_KERNEL); ++ if (!sp->u.iocb_cmd.u.ctarg.req) { ++ ql_log(ql_log_warn, vha, 0xd041, ++ "%s: Failed to allocate ct_sns request.\n", ++ __func__); ++ goto done_free_sp; ++ } ++ ++ sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = sizeof(struct ct_sns_pkt); ++ sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev, ++ sp->u.iocb_cmd.u.ctarg.rsp_allocated_size, ++ &sp->u.iocb_cmd.u.ctarg.rsp_dma, ++ GFP_KERNEL); ++ if (!sp->u.iocb_cmd.u.ctarg.rsp) { ++ ql_log(ql_log_warn, vha, 0xd041, ++ "%s: Failed to allocate ct_sns response.\n", ++ __func__); ++ goto done_free_sp; ++ } + + /* CT_IU preamble */ +- ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GFF_ID_CMD, +- GFF_ID_RSP_SIZE); ++ ct_req = qla2x00_prep_ct_req(sp->u.iocb_cmd.u.ctarg.req, GFF_ID_CMD, GFF_ID_RSP_SIZE); + + ct_req->req.gff_id.port_id[0] = fcport->d_id.b.domain; + ct_req->req.gff_id.port_id[1] = fcport->d_id.b.area; + ct_req->req.gff_id.port_id[2] = fcport->d_id.b.al_pa; + +- sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns; +- sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma; +- sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns; +- sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma; + sp->u.iocb_cmd.u.ctarg.req_size = GFF_ID_REQ_SIZE; + sp->u.iocb_cmd.u.ctarg.rsp_size = GFF_ID_RSP_SIZE; + sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS; + +- ql_dbg(ql_dbg_disc, vha, 0x2132, +- "Async-%s hdl=%x %8phC.\n", sp->name, +- sp->handle, fcport->port_name); +- + rval = qla2x00_start_sp(sp); +- if (rval != QLA_SUCCESS) ++ ++ if (rval != QLA_SUCCESS) { ++ rval = QLA_FUNCTION_FAILED; + goto done_free_sp; ++ } else { ++ ql_dbg(ql_dbg_disc, vha, 0x3074, ++ "Async-%s hdl=%x portid %06x\n", ++ sp->name, sp->handle, fcport->d_id.b24); ++ } ++ ++ wait_for_completion(sp->comp); ++ rval = sp->rc; + +- return rval; + done_free_sp: ++ if (sp->u.iocb_cmd.u.ctarg.req) { ++ dma_free_coherent(&vha->hw->pdev->dev, ++ sp->u.iocb_cmd.u.ctarg.req_allocated_size, ++ sp->u.iocb_cmd.u.ctarg.req, ++ sp->u.iocb_cmd.u.ctarg.req_dma); ++ sp->u.iocb_cmd.u.ctarg.req = NULL; ++ } ++ ++ if (sp->u.iocb_cmd.u.ctarg.rsp) { ++ dma_free_coherent(&vha->hw->pdev->dev, ++ sp->u.iocb_cmd.u.ctarg.rsp_allocated_size, ++ sp->u.iocb_cmd.u.ctarg.rsp, ++ sp->u.iocb_cmd.u.ctarg.rsp_dma); ++ sp->u.iocb_cmd.u.ctarg.rsp = NULL; ++ } ++ + /* ref: INIT */ + kref_put(&sp->cmd_kref, qla2x00_sp_release); +- fcport->flags &= ~FCF_ASYNC_SENT; + return rval; + } + +@@ -3577,7 +3628,7 @@ login_logout: + do_delete) { + if (fcport->loop_id != FC_NO_LOOP_ID) { + if (fcport->flags & FCF_FCP2_DEVICE) +- fcport->logout_on_delete = 0; ++ continue; + + ql_log(ql_log_warn, vha, 0x20f0, + "%s %d %8phC post del sess\n", +diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c +index c3ba2995209bd..b81797a3ab617 100644 +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -47,6 +47,7 @@ qla2x00_sp_timeout(struct timer_list *t) + { + srb_t *sp = from_timer(sp, t, u.iocb_cmd.timer); + struct srb_iocb *iocb; ++ scsi_qla_host_t *vha = sp->vha; + + WARN_ON(irqs_disabled()); + iocb = &sp->u.iocb_cmd; +@@ -54,6 +55,12 @@ qla2x00_sp_timeout(struct timer_list *t) + + /* ref: TMR */ + kref_put(&sp->cmd_kref, qla2x00_sp_release); ++ ++ if (vha && qla2x00_isp_reg_stat(vha->hw)) { ++ ql_log(ql_log_info, vha, 0x9008, ++ "PCI/Register disconnect.\n"); ++ qla_pci_set_eeh_busy(vha); ++ } + } + + void qla2x00_sp_free(srb_t *sp) +@@ -161,6 +168,7 @@ 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, +@@ -168,6 +176,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); + abt_iocb = &sp->u.iocb_cmd; + sp->type = SRB_ABT_CMD; + sp->name = "abort"; +@@ -341,7 +350,7 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, + lio->u.logio.flags |= SRB_LOGIN_PRLI_ONLY; + } else { + if (vha->hw->flags.edif_enabled && +- vha->e_dbell.db_flags & EDB_ACTIVE) { ++ DBELL_ACTIVE(vha)) { + lio->u.logio.flags |= + (SRB_LOGIN_FCSP | SRB_LOGIN_SKIP_PRLI); + ql_dbg(ql_dbg_disc, vha, 0x2072, +@@ -881,7 +890,7 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, + break; + case DSC_LS_PLOGI_COMP: + if (vha->hw->flags.edif_enabled && +- vha->e_dbell.db_flags & EDB_ACTIVE) { ++ DBELL_ACTIVE(vha)) { + /* check to see if App support secure or not */ + qla24xx_post_gpdb_work(vha, fcport, 0); + break; +@@ -1477,7 +1486,7 @@ static int qla_chk_secure_login(scsi_qla_host_t *vha, fc_port_t *fcport, + qla2x00_post_aen_work(vha, FCH_EVT_PORT_ONLINE, + fcport->d_id.b24); + +- if (vha->e_dbell.db_flags == EDB_ACTIVE) { ++ if (DBELL_ACTIVE(vha)) { + ql_dbg(ql_dbg_disc, vha, 0x20ef, + "%s %d %8phC EDIF: post DB_AUTH: AUTH needed\n", + __func__, __LINE__, fcport->port_name); +@@ -1764,8 +1773,16 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport) + break; + + case DSC_LOGIN_PEND: +- if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) ++ if (vha->hw->flags.edif_enabled) ++ break; ++ ++ if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) { ++ ql_dbg(ql_dbg_disc, vha, 0x2118, ++ "%s %d %8phC post %s PRLI\n", ++ __func__, __LINE__, fcport->port_name, ++ NVME_TARGET(vha->hw, fcport) ? "NVME" : "FC"); + qla24xx_post_prli_work(vha, fcport); ++ } + break; + + case DSC_UPD_FCPORT: +@@ -1819,19 +1836,41 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea) + case RSCN_PORT_ADDR: + fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1); + if (fcport) { +- if (fcport->flags & FCF_FCP2_DEVICE) { ++ if (fcport->flags & FCF_FCP2_DEVICE && ++ atomic_read(&fcport->state) == FCS_ONLINE) { + ql_dbg(ql_dbg_disc, vha, 0x2115, + "Delaying session delete for FCP2 portid=%06x %8phC ", + fcport->d_id.b24, fcport->port_name); + return; + } +- fcport->scan_needed = 1; +- fcport->rscn_gen++; ++ ++ if (vha->hw->flags.edif_enabled && DBELL_ACTIVE(vha)) { ++ /* ++ * On ipsec start by remote port, Target port ++ * may use RSCN to trigger initiator to ++ * relogin. If driver is already in the ++ * process of a relogin, then ignore the RSCN ++ * and allow the current relogin to continue. ++ * This reduces thrashing of the connection. ++ */ ++ if (atomic_read(&fcport->state) == FCS_ONLINE) { ++ /* ++ * If state = online, then set scan_needed=1 to do relogin. ++ * Otherwise we're already in the middle of a relogin ++ */ ++ fcport->scan_needed = 1; ++ fcport->rscn_gen++; ++ } ++ } else { ++ fcport->scan_needed = 1; ++ fcport->rscn_gen++; ++ } + } + break; + case RSCN_AREA_ADDR: + list_for_each_entry(fcport, &vha->vp_fcports, list) { +- if (fcport->flags & FCF_FCP2_DEVICE) ++ if (fcport->flags & FCF_FCP2_DEVICE && ++ atomic_read(&fcport->state) == FCS_ONLINE) + continue; + + if ((ea->id.b24 & 0xffff00) == (fcport->d_id.b24 & 0xffff00)) { +@@ -1842,7 +1881,8 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea) + break; + case RSCN_DOM_ADDR: + list_for_each_entry(fcport, &vha->vp_fcports, list) { +- if (fcport->flags & FCF_FCP2_DEVICE) ++ if (fcport->flags & FCF_FCP2_DEVICE && ++ atomic_read(&fcport->state) == FCS_ONLINE) + continue; + + if ((ea->id.b24 & 0xff0000) == (fcport->d_id.b24 & 0xff0000)) { +@@ -1854,7 +1894,8 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea) + case RSCN_FAB_ADDR: + default: + list_for_each_entry(fcport, &vha->vp_fcports, list) { +- if (fcport->flags & FCF_FCP2_DEVICE) ++ if (fcport->flags & FCF_FCP2_DEVICE && ++ atomic_read(&fcport->state) == FCS_ONLINE) + continue; + + fcport->scan_needed = 1; +@@ -1981,12 +2022,14 @@ 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); + sp->type = SRB_TM_CMD; + sp->name = "tmf"; + qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha), +@@ -2105,6 +2148,13 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea) + } + + if (N2N_TOPO(vha->hw)) { ++ if (ea->fcport->n2n_link_reset_cnt == ++ vha->hw->login_retry_count && ++ ea->fcport->flags & FCF_FCSP_DEVICE) { ++ /* remote authentication app just started */ ++ ea->fcport->n2n_link_reset_cnt = 0; ++ } ++ + if (ea->fcport->n2n_link_reset_cnt < + vha->hw->login_retry_count) { + ea->fcport->n2n_link_reset_cnt++; +@@ -4246,7 +4296,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) + * fw shal not send PRLI after PLOGI Acc + */ + if (ha->flags.edif_enabled && +- vha->e_dbell.db_flags & EDB_ACTIVE) { ++ DBELL_ACTIVE(vha)) { + ha->fw_options[3] |= BIT_15; + ha->flags.n2n_fw_acc_sec = 1; + } else { +@@ -4490,6 +4540,8 @@ qla2x00_init_rings(scsi_qla_host_t *vha) + BIT_6) != 0; + ql_dbg(ql_dbg_init, vha, 0x00bc, "FA-WWPN Support: %s.\n", + (ha->flags.fawwpn_enabled) ? "enabled" : "disabled"); ++ /* Init_cb will be reused for other command(s). Save a backup copy of port_name */ ++ memcpy(ha->port_name, ha->init_cb->port_name, WWN_SIZE); + } + + /* ELS pass through payload is limit by frame size. */ +@@ -5402,8 +5454,7 @@ qla2x00_configure_loop(scsi_qla_host_t *vha) + * use link up to wake up app to get ready for + * authentication. + */ +- if (ha->flags.edif_enabled && +- !(vha->e_dbell.db_flags & EDB_ACTIVE)) ++ if (ha->flags.edif_enabled && DBELL_INACTIVE(vha)) + qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, + ha->link_data_rate); + +@@ -5470,6 +5521,22 @@ static int qla2x00_configure_n2n_loop(scsi_qla_host_t *vha) + return QLA_FUNCTION_FAILED; + } + ++static void ++qla_reinitialize_link(scsi_qla_host_t *vha) ++{ ++ int rval; ++ ++ atomic_set(&vha->loop_state, LOOP_DOWN); ++ atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); ++ rval = qla2x00_full_login_lip(vha); ++ if (rval == QLA_SUCCESS) { ++ ql_dbg(ql_dbg_disc, vha, 0xd050, "Link reinitialized\n"); ++ } else { ++ ql_dbg(ql_dbg_disc, vha, 0xd051, ++ "Link reinitialization failed (%d)\n", rval); ++ } ++} ++ + /* + * qla2x00_configure_local_loop + * Updates Fibre Channel Device Database with local loop devices. +@@ -5521,6 +5588,19 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) + spin_unlock_irqrestore(&vha->work_lock, flags); + + if (vha->scan.scan_retry < MAX_SCAN_RETRIES) { ++ u8 loop_map_entries = 0; ++ int rc; ++ ++ rc = qla2x00_get_fcal_position_map(vha, NULL, ++ &loop_map_entries); ++ if (rc == QLA_SUCCESS && loop_map_entries > 1) { ++ /* ++ * There are devices that are still not logged ++ * in. Reinitialize to give them a chance. ++ */ ++ qla_reinitialize_link(vha); ++ return QLA_FUNCTION_FAILED; ++ } + set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); + set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); + } +@@ -5749,8 +5829,6 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport) + if (atomic_read(&fcport->state) == FCS_ONLINE) + return; + +- qla2x00_set_fcport_state(fcport, FCS_ONLINE); +- + rport_ids.node_name = wwn_to_u64(fcport->node_name); + rport_ids.port_name = wwn_to_u64(fcport->port_name); + rport_ids.port_id = fcport->d_id.b.domain << 16 | +@@ -5858,7 +5936,6 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) + qla2x00_reg_remote_port(vha, fcport); + break; + case MODE_TARGET: +- qla2x00_set_fcport_state(fcport, FCS_ONLINE); + if (!vha->vha_tgt.qla_tgt->tgt_stop && + !vha->vha_tgt.qla_tgt->tgt_stopped) + qlt_fc_port_added(vha, fcport); +@@ -5873,6 +5950,8 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) + break; + } + ++ qla2x00_set_fcport_state(fcport, FCS_ONLINE); ++ + if (IS_IIDMA_CAPABLE(vha->hw) && vha->hw->flags.gpsc_supported) { + if (fcport->id_changed) { + fcport->id_changed = 0; +@@ -9663,6 +9742,12 @@ int qla2xxx_disable_port(struct Scsi_Host *host) + + vha->hw->flags.port_isolated = 1; + ++ if (qla2x00_isp_reg_stat(vha->hw)) { ++ ql_log(ql_log_info, vha, 0x9006, ++ "PCI/Register disconnect, exiting.\n"); ++ qla_pci_set_eeh_busy(vha); ++ return FAILED; ++ } + if (qla2x00_chip_is_down(vha)) + return 0; + +@@ -9678,6 +9763,13 @@ int qla2xxx_enable_port(struct Scsi_Host *host) + { + scsi_qla_host_t *vha = shost_priv(host); + ++ if (qla2x00_isp_reg_stat(vha->hw)) { ++ ql_log(ql_log_info, vha, 0x9001, ++ "PCI/Register disconnect, exiting.\n"); ++ qla_pci_set_eeh_busy(vha); ++ return FAILED; ++ } ++ + vha->hw->flags.port_isolated = 0; + /* Set the flag to 1, so that isp_abort can proceed */ + vha->flags.online = 1; +diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c +index 606228f4a8b53..42ce4e1fe7441 100644 +--- a/drivers/scsi/qla2xxx/qla_iocb.c ++++ b/drivers/scsi/qla2xxx/qla_iocb.c +@@ -2819,7 +2819,7 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) + sp->vha->qla_stats.control_requests++; + } + +-static void ++void + qla2x00_els_dcmd2_iocb_timeout(void *data) + { + srb_t *sp = data; +@@ -2882,6 +2882,9 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res) + sp->name, res, sp->handle, fcport->d_id.b24, fcport->port_name); + + fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE); ++ /* For edif, set logout on delete to ensure any residual key from FW is flushed.*/ ++ fcport->logout_on_delete = 1; ++ fcport->chip_reset = vha->hw->base_qpair->chip_reset; + + if (sp->flags & SRB_WAKEUP_ON_COMP) + complete(&lio->u.els_plogi.comp); +@@ -3065,8 +3068,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, + elsio->u.els_plogi.els_cmd = els_opcode; + elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode; + +- if (els_opcode == ELS_DCMD_PLOGI && vha->hw->flags.edif_enabled && +- vha->e_dbell.db_flags & EDB_ACTIVE) { ++ if (els_opcode == ELS_DCMD_PLOGI && DBELL_ACTIVE(vha)) { + struct fc_els_flogi *p = ptr; + + p->fl_csp.sp_features |= cpu_to_be16(FC_SP_FT_SEC); +diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c +index 62d2f14848e7b..b218f97396195 100644 +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -1354,9 +1354,7 @@ skip_rio: + if (!vha->vp_idx) { + if (ha->flags.fawwpn_enabled && + (ha->current_topology == ISP_CFG_F)) { +- void *wwpn = ha->init_cb->port_name; +- +- memcpy(vha->port_name, wwpn, WWN_SIZE); ++ memcpy(vha->port_name, ha->port_name, WWN_SIZE); + fc_host_port_name(vha->host) = + wwn_to_u64(vha->port_name); + ql_dbg(ql_dbg_init + ql_dbg_verbose, +@@ -2635,7 +2633,7 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, + } + + if (unlikely(logit)) +- ql_log(ql_dbg_io, fcport->vha, 0x5060, ++ ql_dbg(ql_dbg_io, fcport->vha, 0x5060, + "NVME-%s ERR Handling - hdl=%x status(%x) tr_len:%x resid=%x ox_id=%x\n", + sp->name, sp->handle, comp_status, + fd->transferred_length, le32_to_cpu(sts->residual_len), +@@ -3422,6 +3420,7 @@ check_scsi_status: + case CS_PORT_UNAVAILABLE: + case CS_TIMEOUT: + case CS_RESET: ++ case CS_EDIF_INV_REQ: + + /* + * We are going to have the fc class block the rport +@@ -3492,7 +3491,7 @@ check_scsi_status: + + out: + if (logit) +- ql_log(ql_dbg_io, fcport->vha, 0x3022, ++ ql_dbg(ql_dbg_io, fcport->vha, 0x3022, + "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n", + comp_status, scsi_status, res, vha->host_no, + cp->device->id, cp->device->lun, fcport->d_id.b.domain, +@@ -4416,16 +4415,12 @@ msix_register_fail: + } + + /* Enable MSI-X vector for response queue update for queue 0 */ +- if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { +- if (ha->msixbase && ha->mqiobase && +- (ha->max_rsp_queues > 1 || ha->max_req_queues > 1 || +- ql2xmqsupport)) +- ha->mqenable = 1; +- } else +- if (ha->mqiobase && +- (ha->max_rsp_queues > 1 || ha->max_req_queues > 1 || +- ql2xmqsupport)) +- ha->mqenable = 1; ++ if (IS_MQUE_CAPABLE(ha) && ++ (ha->msixbase && ha->mqiobase && ha->max_qpairs)) ++ ha->mqenable = 1; ++ else ++ ha->mqenable = 0; ++ + ql_dbg(ql_dbg_multiq, vha, 0xc005, + "mqiobase=%p, max_rsp_queues=%d, max_req_queues=%d.\n", + ha->mqiobase, ha->max_rsp_queues, ha->max_req_queues); +diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c +index 950c5903e7992..5bcb8da4360f2 100644 +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -238,6 +238,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) + ql_dbg(ql_dbg_mbx, vha, 0x1112, + "mbox[%d]<-0x%04x\n", cnt, *iptr); + wrt_reg_word(optr, *iptr); ++ } else { ++ wrt_reg_word(optr, 0); + } + + mboxes >>= 1; +@@ -274,6 +276,12 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) + atomic_inc(&ha->num_pend_mbx_stage3); + if (!wait_for_completion_timeout(&ha->mbx_intr_comp, + mcp->tov * HZ)) { ++ ql_dbg(ql_dbg_mbx, vha, 0x117a, ++ "cmd=%x Timeout.\n", command); ++ spin_lock_irqsave(&ha->hardware_lock, flags); ++ clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); ++ spin_unlock_irqrestore(&ha->hardware_lock, flags); ++ + if (chip_reset != ha->chip_reset) { + eeh_delay = ha->flags.eeh_busy ? 1 : 0; + +@@ -286,12 +294,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) + rval = QLA_ABORTED; + goto premature_exit; + } +- ql_dbg(ql_dbg_mbx, vha, 0x117a, +- "cmd=%x Timeout.\n", command); +- spin_lock_irqsave(&ha->hardware_lock, flags); +- clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); +- spin_unlock_irqrestore(&ha->hardware_lock, flags); +- + } else if (ha->flags.purge_mbox || + chip_reset != ha->chip_reset) { + eeh_delay = ha->flags.eeh_busy ? 1 : 0; +@@ -3060,7 +3062,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha) + * Kernel context. + */ + int +-qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map) ++qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map, ++ u8 *num_entries) + { + int rval; + mbx_cmd_t mc; +@@ -3100,6 +3103,8 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map) + + if (pos_map) + memcpy(pos_map, pmap, FCAL_MAP_SIZE); ++ if (num_entries) ++ *num_entries = pmap[0]; + } + dma_pool_free(ha->s_dma_pool, pmap, pmap_dma); + +diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c +index e6b5c4ccce97b..eb43a5f1b3992 100644 +--- a/drivers/scsi/qla2xxx/qla_mid.c ++++ b/drivers/scsi/qla2xxx/qla_mid.c +@@ -166,9 +166,13 @@ qla24xx_disable_vp(scsi_qla_host_t *vha) + int ret = QLA_SUCCESS; + fc_port_t *fcport; + +- if (vha->hw->flags.edif_enabled) ++ if (vha->hw->flags.edif_enabled) { ++ if (DBELL_ACTIVE(vha)) ++ qla2x00_post_aen_work(vha, FCH_EVT_VENDOR_UNIQUE, ++ FCH_EVT_VENDOR_UNIQUE_VPORT_DOWN); + /* delete sessions and flush sa_indexes */ + qla2x00_wait_for_sess_deletion(vha); ++ } + + if (vha->hw->flags.fw_started) + ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL); +diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c +index 1bf3ab10846aa..3e167dc4eec72 100644 +--- a/drivers/scsi/qla2xxx/qla_nvme.c ++++ b/drivers/scsi/qla2xxx/qla_nvme.c +@@ -35,11 +35,6 @@ int qla_nvme_register_remote(struct scsi_qla_host *vha, struct fc_port *fcport) + (fcport->nvme_flag & NVME_FLAG_REGISTERED)) + return 0; + +- if (atomic_read(&fcport->state) == FCS_ONLINE) +- return 0; +- +- qla2x00_set_fcport_state(fcport, FCS_ONLINE); +- + fcport->nvme_flag &= ~NVME_FLAG_RESETTING; + + memset(&req, 0, sizeof(struct nvme_fc_port_info)); +diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c +index e683b1c01c9f5..6542a258cb751 100644 +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -333,6 +333,11 @@ MODULE_PARM_DESC(ql2xabts_wait_nvme, + "To wait for ABTS response on I/O timeouts for NVMe. (default: 1)"); + + ++u32 ql2xdelay_before_pci_error_handling = 5; ++module_param(ql2xdelay_before_pci_error_handling, uint, 0644); ++MODULE_PARM_DESC(ql2xdelay_before_pci_error_handling, ++ "Number of seconds delayed before qla begin PCI error self-handling (default: 5).\n"); ++ + static void qla2x00_clear_drv_active(struct qla_hw_data *); + static void qla2x00_free_device(scsi_qla_host_t *); + static int qla2xxx_map_queues(struct Scsi_Host *shost); +@@ -1333,21 +1338,20 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) + /* + * Returns: QLA_SUCCESS or QLA_FUNCTION_FAILED. + */ +-int +-qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, +- uint64_t l, enum nexus_wait_type type) ++static int ++__qla2x00_eh_wait_for_pending_commands(struct qla_qpair *qpair, unsigned int t, ++ uint64_t l, enum nexus_wait_type type) + { + int cnt, match, status; + unsigned long flags; +- struct qla_hw_data *ha = vha->hw; +- struct req_que *req; ++ scsi_qla_host_t *vha = qpair->vha; ++ struct req_que *req = qpair->req; + srb_t *sp; + struct scsi_cmnd *cmd; + + status = QLA_SUCCESS; + +- spin_lock_irqsave(&ha->hardware_lock, flags); +- req = vha->req; ++ spin_lock_irqsave(qpair->qp_lock_ptr, flags); + for (cnt = 1; status == QLA_SUCCESS && + cnt < req->num_outstanding_cmds; cnt++) { + sp = req->outstanding_cmds[cnt]; +@@ -1374,15 +1378,35 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, + if (!match) + continue; + +- spin_unlock_irqrestore(&ha->hardware_lock, flags); ++ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + status = qla2x00_eh_wait_on_command(cmd); +- spin_lock_irqsave(&ha->hardware_lock, flags); ++ spin_lock_irqsave(qpair->qp_lock_ptr, flags); + } +- spin_unlock_irqrestore(&ha->hardware_lock, flags); ++ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + + return status; + } + ++int ++qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, ++ uint64_t l, enum nexus_wait_type type) ++{ ++ struct qla_qpair *qpair; ++ struct qla_hw_data *ha = vha->hw; ++ int i, status = QLA_SUCCESS; ++ ++ status = __qla2x00_eh_wait_for_pending_commands(ha->base_qpair, t, l, ++ type); ++ for (i = 0; status == QLA_SUCCESS && i < ha->max_qpairs; i++) { ++ qpair = ha->queue_pair_map[i]; ++ if (!qpair) ++ continue; ++ status = __qla2x00_eh_wait_for_pending_commands(qpair, t, l, ++ type); ++ } ++ return status; ++} ++ + static char *reset_errors[] = { + "HBA not online", + "HBA not ready", +@@ -1416,7 +1440,7 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) + return err; + + if (fcport->deleted) +- return SUCCESS; ++ return FAILED; + + ql_log(ql_log_info, vha, 0x8009, + "DEVICE RESET ISSUED nexus=%ld:%d:%llu cmd=%p.\n", vha->host_no, +@@ -1484,7 +1508,7 @@ qla2xxx_eh_target_reset(struct scsi_cmnd *cmd) + return err; + + if (fcport->deleted) +- return SUCCESS; ++ return FAILED; + + ql_log(ql_log_info, vha, 0x8009, + "TARGET RESET ISSUED nexus=%ld:%d cmd=%p.\n", vha->host_no, +@@ -5466,7 +5490,7 @@ qla2x00_do_work(struct scsi_qla_host *vha) + e->u.fcport.fcport, false); + break; + case QLA_EVT_SA_REPLACE: +- qla24xx_issue_sa_replace_iocb(vha, e); ++ rc = qla24xx_issue_sa_replace_iocb(vha, e); + break; + } + +@@ -7232,6 +7256,44 @@ static void qla_heart_beat(struct scsi_qla_host *vha, u16 dpc_started) + } + } + ++static void qla_wind_down_chip(scsi_qla_host_t *vha) ++{ ++ struct qla_hw_data *ha = vha->hw; ++ ++ if (!ha->flags.eeh_busy) ++ return; ++ if (ha->pci_error_state) ++ /* system is trying to recover */ ++ return; ++ ++ /* ++ * Current system is not handling PCIE error. At this point, this is ++ * best effort to wind down the adapter. ++ */ ++ if (time_after_eq(jiffies, ha->eeh_jif + ql2xdelay_before_pci_error_handling * HZ) && ++ !ha->flags.eeh_flush) { ++ ql_log(ql_log_info, vha, 0x9009, ++ "PCI Error detected, attempting to reset hardware.\n"); ++ ++ ha->isp_ops->reset_chip(vha); ++ ha->isp_ops->disable_intrs(ha); ++ ++ ha->flags.eeh_flush = EEH_FLUSH_RDY; ++ ha->eeh_jif = jiffies; ++ ++ } else if (ha->flags.eeh_flush == EEH_FLUSH_RDY && ++ time_after_eq(jiffies, ha->eeh_jif + 5 * HZ)) { ++ pci_clear_master(ha->pdev); ++ ++ /* flush all command */ ++ qla2x00_abort_isp_cleanup(vha); ++ ha->flags.eeh_flush = EEH_FLUSH_DONE; ++ ++ ql_log(ql_log_info, vha, 0x900a, ++ "PCI Error handling complete, all IOs aborted.\n"); ++ } ++} ++ + /************************************************************************** + * qla2x00_timer + * +@@ -7255,6 +7317,8 @@ qla2x00_timer(struct timer_list *t) + fc_port_t *fcport = NULL; + + if (ha->flags.eeh_busy) { ++ qla_wind_down_chip(vha); ++ + ql_dbg(ql_dbg_timer, vha, 0x6000, + "EEH = %d, restarting timer.\n", + ha->flags.eeh_busy); +@@ -7835,6 +7899,9 @@ void qla_pci_set_eeh_busy(struct scsi_qla_host *vha) + + spin_lock_irqsave(&base_vha->work_lock, flags); + if (!ha->flags.eeh_busy) { ++ ha->eeh_jif = jiffies; ++ ha->flags.eeh_flush = 0; ++ + ha->flags.eeh_busy = 1; + do_cleanup = true; + } +diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c +index ae5eaa4a9283a..7ab3c9e4d4783 100644 +--- a/drivers/scsi/qla2xxx/qla_target.c ++++ b/drivers/scsi/qla2xxx/qla_target.c +@@ -4815,7 +4815,7 @@ static int qlt_handle_login(struct scsi_qla_host *vha, + } + + if (vha->hw->flags.edif_enabled) { +- if (!(vha->e_dbell.db_flags & EDB_ACTIVE)) { ++ if (DBELL_INACTIVE(vha)) { + ql_dbg(ql_dbg_disc, vha, 0xffff, + "%s %d Term INOT due to app not started lid=%d, NportID %06X ", + __func__, __LINE__, loop_id, port_id.b24); +diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c +index 5947b9d5746e1..f46ae53917582 100644 +--- a/drivers/scsi/scsi_transport_iscsi.c ++++ b/drivers/scsi/scsi_transport_iscsi.c +@@ -2283,16 +2283,8 @@ static void iscsi_if_disconnect_bound_ep(struct iscsi_cls_conn *conn, + } + } + +-static int iscsi_if_stop_conn(struct iscsi_transport *transport, +- struct iscsi_uevent *ev) ++static int iscsi_if_stop_conn(struct iscsi_cls_conn *conn, int flag) + { +- int flag = ev->u.stop_conn.flag; +- struct iscsi_cls_conn *conn; +- +- conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid); +- if (!conn) +- return -EINVAL; +- + ISCSI_DBG_TRANS_CONN(conn, "iscsi if conn stop.\n"); + /* + * If this is a termination we have to call stop_conn with that flag +@@ -2368,6 +2360,55 @@ static void iscsi_cleanup_conn_work_fn(struct work_struct *work) + ISCSI_DBG_TRANS_CONN(conn, "cleanup done.\n"); + } + ++static int iscsi_iter_force_destroy_conn_fn(struct device *dev, void *data) ++{ ++ struct iscsi_transport *transport; ++ struct iscsi_cls_conn *conn; ++ ++ if (!iscsi_is_conn_dev(dev)) ++ return 0; ++ ++ conn = iscsi_dev_to_conn(dev); ++ transport = conn->transport; ++ ++ if (READ_ONCE(conn->state) != ISCSI_CONN_DOWN) ++ iscsi_if_stop_conn(conn, STOP_CONN_TERM); ++ ++ transport->destroy_conn(conn); ++ return 0; ++} ++ ++/** ++ * iscsi_force_destroy_session - destroy a session from the kernel ++ * @session: session to destroy ++ * ++ * Force the destruction of a session from the kernel. This should only be ++ * used when userspace is no longer running during system shutdown. ++ */ ++void iscsi_force_destroy_session(struct iscsi_cls_session *session) ++{ ++ struct iscsi_transport *transport = session->transport; ++ unsigned long flags; ++ ++ WARN_ON_ONCE(system_state == SYSTEM_RUNNING); ++ ++ spin_lock_irqsave(&sesslock, flags); ++ if (list_empty(&session->sess_list)) { ++ spin_unlock_irqrestore(&sesslock, flags); ++ /* ++ * Conn/ep is already freed. Session is being torn down via ++ * async path. For shutdown we don't care about it so return. ++ */ ++ return; ++ } ++ spin_unlock_irqrestore(&sesslock, flags); ++ ++ device_for_each_child(&session->dev, NULL, ++ iscsi_iter_force_destroy_conn_fn); ++ transport->destroy_session(session); ++} ++EXPORT_SYMBOL_GPL(iscsi_force_destroy_session); ++ + void iscsi_free_session(struct iscsi_cls_session *session) + { + ISCSI_DBG_TRANS_SESSION(session, "Freeing session\n"); +@@ -3739,7 +3780,12 @@ static int iscsi_if_transport_conn(struct iscsi_transport *transport, + case ISCSI_UEVENT_DESTROY_CONN: + return iscsi_if_destroy_conn(transport, ev); + case ISCSI_UEVENT_STOP_CONN: +- return iscsi_if_stop_conn(transport, ev); ++ conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ++ ev->u.stop_conn.cid); ++ if (!conn) ++ return -EINVAL; ++ ++ return iscsi_if_stop_conn(conn, ev->u.stop_conn.flag); + } + + /* +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index 3c98f08dc25d9..d771a1988f942 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -191,7 +191,7 @@ static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size); + static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp); + static Sg_fd *sg_add_sfp(Sg_device * sdp); + static void sg_remove_sfp(struct kref *); +-static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id); ++static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id, bool *busy); + static Sg_request *sg_add_request(Sg_fd * sfp); + static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); + static Sg_device *sg_get_dev(int dev); +@@ -445,6 +445,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) + Sg_fd *sfp; + Sg_request *srp; + int req_pack_id = -1; ++ bool busy; + sg_io_hdr_t *hp; + struct sg_header *old_hdr; + int retval; +@@ -467,20 +468,16 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) + if (retval) + return retval; + +- srp = sg_get_rq_mark(sfp, req_pack_id); ++ srp = sg_get_rq_mark(sfp, req_pack_id, &busy); + if (!srp) { /* now wait on packet to arrive */ +- if (atomic_read(&sdp->detaching)) +- return -ENODEV; + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + retval = wait_event_interruptible(sfp->read_wait, +- (atomic_read(&sdp->detaching) || +- (srp = sg_get_rq_mark(sfp, req_pack_id)))); +- if (atomic_read(&sdp->detaching)) +- return -ENODEV; +- if (retval) +- /* -ERESTARTSYS as signal hit process */ +- return retval; ++ ((srp = sg_get_rq_mark(sfp, req_pack_id, &busy)) || ++ (!busy && atomic_read(&sdp->detaching)))); ++ if (!srp) ++ /* signal or detaching */ ++ return retval ? retval : -ENODEV; + } + if (srp->header.interface_id != '\0') + return sg_new_read(sfp, buf, count, srp); +@@ -941,9 +938,7 @@ sg_ioctl_common(struct file *filp, Sg_device *sdp, Sg_fd *sfp, + if (result < 0) + return result; + result = wait_event_interruptible(sfp->read_wait, +- (srp_done(sfp, srp) || atomic_read(&sdp->detaching))); +- if (atomic_read(&sdp->detaching)) +- return -ENODEV; ++ srp_done(sfp, srp)); + write_lock_irq(&sfp->rq_list_lock); + if (srp->done) { + srp->done = 2; +@@ -2056,19 +2051,28 @@ sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp) + } + + static Sg_request * +-sg_get_rq_mark(Sg_fd * sfp, int pack_id) ++sg_get_rq_mark(Sg_fd * sfp, int pack_id, bool *busy) + { + Sg_request *resp; + unsigned long iflags; + ++ *busy = false; + write_lock_irqsave(&sfp->rq_list_lock, iflags); + list_for_each_entry(resp, &sfp->rq_list, entry) { +- /* look for requests that are ready + not SG_IO owned */ +- if ((1 == resp->done) && (!resp->sg_io_owned) && ++ /* look for requests that are not SG_IO owned */ ++ if ((!resp->sg_io_owned) && + ((-1 == pack_id) || (resp->header.pack_id == pack_id))) { +- resp->done = 2; /* guard against other readers */ +- write_unlock_irqrestore(&sfp->rq_list_lock, iflags); +- return resp; ++ switch (resp->done) { ++ case 0: /* request active */ ++ *busy = true; ++ break; ++ case 1: /* request done; response ready to return */ ++ resp->done = 2; /* guard against other readers */ ++ write_unlock_irqrestore(&sfp->rq_list_lock, iflags); ++ return resp; ++ case 2: /* response already being returned */ ++ break; ++ } + } + } + write_unlock_irqrestore(&sfp->rq_list_lock, iflags); +@@ -2122,6 +2126,15 @@ sg_remove_request(Sg_fd * sfp, Sg_request * srp) + res = 1; + } + write_unlock_irqrestore(&sfp->rq_list_lock, iflags); ++ ++ /* ++ * If the device is detaching, wakeup any readers in case we just ++ * removed the last response, which would leave nothing for them to ++ * return other than -ENODEV. ++ */ ++ if (unlikely(atomic_read(&sfp->parentdp->detaching))) ++ wake_up_interruptible_all(&sfp->read_wait); ++ + return res; + } + +diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c +index 2e690d8a34440..e3d8de1159b51 100644 +--- a/drivers/scsi/smartpqi/smartpqi_init.c ++++ b/drivers/scsi/smartpqi/smartpqi_init.c +@@ -5310,10 +5310,10 @@ static int pqi_raid_submit_scsi_cmd_with_io_request( + } + + switch (scmd->sc_data_direction) { +- case DMA_TO_DEVICE: ++ case DMA_FROM_DEVICE: + request->data_direction = SOP_READ_FLAG; + break; +- case DMA_FROM_DEVICE: ++ case DMA_TO_DEVICE: + request->data_direction = SOP_WRITE_FLAG; + break; + case DMA_NONE: +diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c +index 4a7248421bcd0..2f6468f22b489 100644 +--- a/drivers/scsi/ufs/ufshcd.c ++++ b/drivers/scsi/ufs/ufshcd.c +@@ -9239,12 +9239,8 @@ EXPORT_SYMBOL(ufshcd_runtime_resume); + int ufshcd_shutdown(struct ufs_hba *hba) + { + if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba)) +- goto out; +- +- pm_runtime_get_sync(hba->dev); ++ ufshcd_suspend(hba); + +- ufshcd_suspend(hba); +-out: + hba->is_powered = false; + /* allow force shutdown even in case of errors */ + return 0; +diff --git a/drivers/soc/amlogic/meson-mx-socinfo.c b/drivers/soc/amlogic/meson-mx-socinfo.c +index 78f0f1aeca578..92125dd65f338 100644 +--- a/drivers/soc/amlogic/meson-mx-socinfo.c ++++ b/drivers/soc/amlogic/meson-mx-socinfo.c +@@ -126,6 +126,7 @@ static int __init meson_mx_socinfo_init(void) + np = of_find_matching_node(NULL, meson_mx_socinfo_analog_top_ids); + if (np) { + analog_top_regmap = syscon_node_to_regmap(np); ++ of_node_put(np); + if (IS_ERR(analog_top_regmap)) + return PTR_ERR(analog_top_regmap); + +diff --git a/drivers/soc/amlogic/meson-secure-pwrc.c b/drivers/soc/amlogic/meson-secure-pwrc.c +index 59bd195fa9c92..2eeea5e1b3b7f 100644 +--- a/drivers/soc/amlogic/meson-secure-pwrc.c ++++ b/drivers/soc/amlogic/meson-secure-pwrc.c +@@ -139,8 +139,10 @@ static int meson_secure_pwrc_probe(struct platform_device *pdev) + } + + pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL); +- if (!pwrc) ++ if (!pwrc) { ++ of_node_put(sm_np); + return -ENOMEM; ++ } + + pwrc->fw = meson_sm_get(sm_np); + of_node_put(sm_np); +diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c +index 75eabfb916cb5..0b2c7fdbaa5b2 100644 +--- a/drivers/soc/fsl/guts.c ++++ b/drivers/soc/fsl/guts.c +@@ -141,7 +141,7 @@ static int fsl_guts_probe(struct platform_device *pdev) + struct device *dev = &pdev->dev; + struct resource *res; + const struct fsl_soc_die_attr *soc_die; +- const char *machine; ++ const char *machine = NULL; + u32 svr; + + /* Initialize guts */ +diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig +index 79b568f82a1c3..499718e131d72 100644 +--- a/drivers/soc/qcom/Kconfig ++++ b/drivers/soc/qcom/Kconfig +@@ -129,6 +129,7 @@ config QCOM_RPMHPD + + config QCOM_RPMPD + tristate "Qualcomm RPM Power domain driver" ++ depends on PM + depends on QCOM_SMD_RPM + help + QCOM RPM Power domain driver to support power-domains with +diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c +index 85f82e195ef8b..1dfdd0b9ba24d 100644 +--- a/drivers/soc/qcom/ocmem.c ++++ b/drivers/soc/qcom/ocmem.c +@@ -194,14 +194,17 @@ struct ocmem *of_get_ocmem(struct device *dev) + devnode = of_parse_phandle(dev->of_node, "sram", 0); + if (!devnode || !devnode->parent) { + dev_err(dev, "Cannot look up sram phandle\n"); ++ of_node_put(devnode); + return ERR_PTR(-ENODEV); + } + + pdev = of_find_device_by_node(devnode->parent); + if (!pdev) { + dev_err(dev, "Cannot find device node %s\n", devnode->name); ++ of_node_put(devnode); + return ERR_PTR(-EPROBE_DEFER); + } ++ of_node_put(devnode); + + ocmem = platform_get_drvdata(pdev); + if (!ocmem) { +diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c +index 8583c1e558aeb..3973accdc9820 100644 +--- a/drivers/soc/qcom/qcom_aoss.c ++++ b/drivers/soc/qcom/qcom_aoss.c +@@ -499,8 +499,10 @@ static int qmp_cooling_devices_register(struct qmp *qmp) + continue; + ret = qmp_cooling_device_add(qmp, &qmp->cooling_devs[count++], + child); +- if (ret) ++ if (ret) { ++ of_node_put(child); + goto unroll; ++ } + } + + if (!count) +diff --git a/drivers/soc/renesas/r8a779a0-sysc.c b/drivers/soc/renesas/r8a779a0-sysc.c +index 7410b9fa9846f..7e1aba9abce24 100644 +--- a/drivers/soc/renesas/r8a779a0-sysc.c ++++ b/drivers/soc/renesas/r8a779a0-sysc.c +@@ -83,11 +83,11 @@ static struct r8a779a0_sysc_area r8a779a0_areas[] __initdata = { + { "a2cv6", R8A779A0_PD_A2CV6, R8A779A0_PD_A3IR }, + { "a2cn2", R8A779A0_PD_A2CN2, R8A779A0_PD_A3IR }, + { "a2imp23", R8A779A0_PD_A2IMP23, R8A779A0_PD_A3IR }, +- { "a2dp1", R8A779A0_PD_A2DP0, R8A779A0_PD_A3IR }, +- { "a2cv2", R8A779A0_PD_A2CV0, R8A779A0_PD_A3IR }, +- { "a2cv3", R8A779A0_PD_A2CV1, R8A779A0_PD_A3IR }, +- { "a2cv5", R8A779A0_PD_A2CV4, R8A779A0_PD_A3IR }, +- { "a2cv7", R8A779A0_PD_A2CV6, R8A779A0_PD_A3IR }, ++ { "a2dp1", R8A779A0_PD_A2DP1, R8A779A0_PD_A3IR }, ++ { "a2cv2", R8A779A0_PD_A2CV2, R8A779A0_PD_A3IR }, ++ { "a2cv3", R8A779A0_PD_A2CV3, R8A779A0_PD_A3IR }, ++ { "a2cv5", R8A779A0_PD_A2CV5, R8A779A0_PD_A3IR }, ++ { "a2cv7", R8A779A0_PD_A2CV7, R8A779A0_PD_A3IR }, + { "a2cn1", R8A779A0_PD_A2CN1, R8A779A0_PD_A3IR }, + { "a1cnn0", R8A779A0_PD_A1CNN0, R8A779A0_PD_A2CN0 }, + { "a1cnn2", R8A779A0_PD_A1CNN2, R8A779A0_PD_A2CN2 }, +diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c +index 67369e941d0d6..b7cdfa65157c6 100644 +--- a/drivers/soundwire/bus.c ++++ b/drivers/soundwire/bus.c +@@ -7,6 +7,7 @@ + #include <linux/pm_runtime.h> + #include <linux/soundwire/sdw_registers.h> + #include <linux/soundwire/sdw.h> ++#include <linux/soundwire/sdw_type.h> + #include "bus.h" + #include "sysfs_local.h" + +@@ -846,15 +847,21 @@ static int sdw_slave_clk_stop_callback(struct sdw_slave *slave, + enum sdw_clk_stop_mode mode, + enum sdw_clk_stop_type type) + { +- int ret; ++ int ret = 0; + +- if (slave->ops && slave->ops->clk_stop) { +- ret = slave->ops->clk_stop(slave, mode, type); +- if (ret < 0) +- return ret; ++ mutex_lock(&slave->sdw_dev_lock); ++ ++ if (slave->probed) { ++ struct device *dev = &slave->dev; ++ struct sdw_driver *drv = drv_to_sdw_driver(dev->driver); ++ ++ if (drv->ops && drv->ops->clk_stop) ++ ret = drv->ops->clk_stop(slave, mode, type); + } + +- return 0; ++ mutex_unlock(&slave->sdw_dev_lock); ++ ++ return ret; + } + + static int sdw_slave_clk_stop_prepare(struct sdw_slave *slave, +@@ -1616,14 +1623,24 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) + } + + /* Update the Slave driver */ +- if (slave_notify && slave->ops && +- slave->ops->interrupt_callback) { +- slave_intr.sdca_cascade = sdca_cascade; +- slave_intr.control_port = clear; +- memcpy(slave_intr.port, &port_status, +- sizeof(slave_intr.port)); +- +- slave->ops->interrupt_callback(slave, &slave_intr); ++ if (slave_notify) { ++ mutex_lock(&slave->sdw_dev_lock); ++ ++ if (slave->probed) { ++ struct device *dev = &slave->dev; ++ struct sdw_driver *drv = drv_to_sdw_driver(dev->driver); ++ ++ if (drv->ops && drv->ops->interrupt_callback) { ++ slave_intr.sdca_cascade = sdca_cascade; ++ slave_intr.control_port = clear; ++ memcpy(slave_intr.port, &port_status, ++ sizeof(slave_intr.port)); ++ ++ drv->ops->interrupt_callback(slave, &slave_intr); ++ } ++ } ++ ++ mutex_unlock(&slave->sdw_dev_lock); + } + + /* Ack interrupt */ +@@ -1697,29 +1714,21 @@ io_err: + static int sdw_update_slave_status(struct sdw_slave *slave, + enum sdw_slave_status status) + { +- unsigned long time; ++ int ret = 0; + +- if (!slave->probed) { +- /* +- * the slave status update is typically handled in an +- * interrupt thread, which can race with the driver +- * probe, e.g. when a module needs to be loaded. +- * +- * make sure the probe is complete before updating +- * status. +- */ +- time = wait_for_completion_timeout(&slave->probe_complete, +- msecs_to_jiffies(DEFAULT_PROBE_TIMEOUT)); +- if (!time) { +- dev_err(&slave->dev, "Probe not complete, timed out\n"); +- return -ETIMEDOUT; +- } ++ mutex_lock(&slave->sdw_dev_lock); ++ ++ if (slave->probed) { ++ struct device *dev = &slave->dev; ++ struct sdw_driver *drv = drv_to_sdw_driver(dev->driver); ++ ++ if (drv->ops && drv->ops->update_status) ++ ret = drv->ops->update_status(slave, status); + } + +- if (!slave->ops || !slave->ops->update_status) +- return 0; ++ mutex_unlock(&slave->sdw_dev_lock); + +- return slave->ops->update_status(slave, status); ++ return ret; + } + + /** +diff --git a/drivers/soundwire/bus_type.c b/drivers/soundwire/bus_type.c +index 893296f3fe395..04b3529f89293 100644 +--- a/drivers/soundwire/bus_type.c ++++ b/drivers/soundwire/bus_type.c +@@ -98,8 +98,6 @@ static int sdw_drv_probe(struct device *dev) + if (!id) + return -ENODEV; + +- slave->ops = drv->ops; +- + /* + * attach to power domain but don't turn on (last arg) + */ +@@ -107,19 +105,23 @@ static int sdw_drv_probe(struct device *dev) + if (ret) + return ret; + ++ mutex_lock(&slave->sdw_dev_lock); ++ + ret = drv->probe(slave, id); + if (ret) { + name = drv->name; + if (!name) + name = drv->driver.name; ++ mutex_unlock(&slave->sdw_dev_lock); ++ + dev_err(dev, "Probe of %s failed: %d\n", name, ret); + dev_pm_domain_detach(dev, false); + return ret; + } + + /* device is probed so let's read the properties now */ +- if (slave->ops && slave->ops->read_prop) +- slave->ops->read_prop(slave); ++ if (drv->ops && drv->ops->read_prop) ++ drv->ops->read_prop(slave); + + /* init the sysfs as we have properties now */ + ret = sdw_slave_sysfs_init(slave); +@@ -139,7 +141,19 @@ static int sdw_drv_probe(struct device *dev) + slave->prop.clk_stop_timeout); + + slave->probed = true; +- complete(&slave->probe_complete); ++ ++ /* ++ * if the probe happened after the bus was started, notify the codec driver ++ * of the current hardware status to e.g. start the initialization. ++ * Errors are only logged as warnings to avoid failing the probe. ++ */ ++ if (drv->ops && drv->ops->update_status) { ++ ret = drv->ops->update_status(slave, slave->status); ++ if (ret < 0) ++ dev_warn(dev, "%s: update_status failed with status %d\n", __func__, ret); ++ } ++ ++ mutex_unlock(&slave->sdw_dev_lock); + + dev_dbg(dev, "probe complete\n"); + +@@ -152,9 +166,15 @@ static int sdw_drv_remove(struct device *dev) + struct sdw_driver *drv = drv_to_sdw_driver(dev->driver); + int ret = 0; + ++ mutex_lock(&slave->sdw_dev_lock); ++ ++ slave->probed = false; ++ + if (drv->remove) + ret = drv->remove(slave); + ++ mutex_unlock(&slave->sdw_dev_lock); ++ + dev_pm_domain_detach(dev, false); + + return ret; +@@ -193,12 +213,8 @@ int __sdw_register_driver(struct sdw_driver *drv, struct module *owner) + + drv->driver.owner = owner; + drv->driver.probe = sdw_drv_probe; +- +- if (drv->remove) +- drv->driver.remove = sdw_drv_remove; +- +- if (drv->shutdown) +- drv->driver.shutdown = sdw_drv_shutdown; ++ drv->driver.remove = sdw_drv_remove; ++ drv->driver.shutdown = sdw_drv_shutdown; + + return driver_register(&drv->driver); + } +diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c +index f5955826b1522..2adc0a75c0515 100644 +--- a/drivers/soundwire/qcom.c ++++ b/drivers/soundwire/qcom.c +@@ -451,6 +451,10 @@ static int qcom_swrm_enumerate(struct sdw_bus *bus) + char *buf1 = (char *)&val1, *buf2 = (char *)&val2; + + for (i = 1; i <= SDW_MAX_DEVICES; i++) { ++ /* do not continue if the status is Not Present */ ++ if (!ctrl->status[i]) ++ continue; ++ + /*SCP_Devid5 - Devid 4*/ + ctrl->reg_read(ctrl, SWRM_ENUMERATOR_SLAVE_DEV_ID_1(i), &val1); + +diff --git a/drivers/soundwire/slave.c b/drivers/soundwire/slave.c +index 669d7573320b7..25e76b5d4a1a3 100644 +--- a/drivers/soundwire/slave.c ++++ b/drivers/soundwire/slave.c +@@ -12,6 +12,7 @@ static void sdw_slave_release(struct device *dev) + { + struct sdw_slave *slave = dev_to_sdw_dev(dev); + ++ mutex_destroy(&slave->sdw_dev_lock); + kfree(slave); + } + +@@ -58,9 +59,9 @@ int sdw_slave_add(struct sdw_bus *bus, + init_completion(&slave->enumeration_complete); + init_completion(&slave->initialization_complete); + slave->dev_num = 0; +- init_completion(&slave->probe_complete); + slave->probed = false; + slave->first_interrupt_done = false; ++ mutex_init(&slave->sdw_dev_lock); + + for (i = 0; i < SDW_MAX_PORTS; i++) + init_completion(&slave->port_ready[i]); +diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c +index 5d4f6b308ef73..ebbe138a56266 100644 +--- a/drivers/soundwire/stream.c ++++ b/drivers/soundwire/stream.c +@@ -13,6 +13,7 @@ + #include <linux/slab.h> + #include <linux/soundwire/sdw_registers.h> + #include <linux/soundwire/sdw.h> ++#include <linux/soundwire/sdw_type.h> + #include <sound/soc.h> + #include "bus.h" + +@@ -401,20 +402,26 @@ static int sdw_do_port_prep(struct sdw_slave_runtime *s_rt, + struct sdw_prepare_ch prep_ch, + enum sdw_port_prep_ops cmd) + { +- const struct sdw_slave_ops *ops = s_rt->slave->ops; +- int ret; ++ int ret = 0; ++ struct sdw_slave *slave = s_rt->slave; + +- if (ops->port_prep) { +- ret = ops->port_prep(s_rt->slave, &prep_ch, cmd); +- if (ret < 0) { +- dev_err(&s_rt->slave->dev, +- "Slave Port Prep cmd %d failed: %d\n", +- cmd, ret); +- return ret; ++ mutex_lock(&slave->sdw_dev_lock); ++ ++ if (slave->probed) { ++ struct device *dev = &slave->dev; ++ struct sdw_driver *drv = drv_to_sdw_driver(dev->driver); ++ ++ if (drv->ops && drv->ops->port_prep) { ++ ret = drv->ops->port_prep(slave, &prep_ch, cmd); ++ if (ret < 0) ++ dev_err(dev, "Slave Port Prep cmd %d failed: %d\n", ++ cmd, ret); + } + } + +- return 0; ++ mutex_unlock(&slave->sdw_dev_lock); ++ ++ return ret; + } + + static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus, +@@ -578,7 +585,7 @@ static int sdw_notify_config(struct sdw_master_runtime *m_rt) + struct sdw_slave_runtime *s_rt; + struct sdw_bus *bus = m_rt->bus; + struct sdw_slave *slave; +- int ret = 0; ++ int ret; + + if (bus->ops->set_bus_conf) { + ret = bus->ops->set_bus_conf(bus, &bus->params); +@@ -589,17 +596,27 @@ static int sdw_notify_config(struct sdw_master_runtime *m_rt) + list_for_each_entry(s_rt, &m_rt->slave_rt_list, m_rt_node) { + slave = s_rt->slave; + +- if (slave->ops->bus_config) { +- ret = slave->ops->bus_config(slave, &bus->params); +- if (ret < 0) { +- dev_err(bus->dev, "Notify Slave: %d failed\n", +- slave->dev_num); +- return ret; ++ mutex_lock(&slave->sdw_dev_lock); ++ ++ if (slave->probed) { ++ struct device *dev = &slave->dev; ++ struct sdw_driver *drv = drv_to_sdw_driver(dev->driver); ++ ++ if (drv->ops && drv->ops->bus_config) { ++ ret = drv->ops->bus_config(slave, &bus->params); ++ if (ret < 0) { ++ dev_err(dev, "Notify Slave: %d failed\n", ++ slave->dev_num); ++ mutex_unlock(&slave->sdw_dev_lock); ++ return ret; ++ } + } + } ++ ++ mutex_unlock(&slave->sdw_dev_lock); + } + +- return ret; ++ return 0; + } + + /** +diff --git a/drivers/spi/spi-altera-dfl.c b/drivers/spi/spi-altera-dfl.c +index ca40923258af3..596e181ae1368 100644 +--- a/drivers/spi/spi-altera-dfl.c ++++ b/drivers/spi/spi-altera-dfl.c +@@ -128,9 +128,9 @@ static int dfl_spi_altera_probe(struct dfl_device *dfl_dev) + struct spi_master *master; + struct altera_spi *hw; + void __iomem *base; +- int err = -ENODEV; ++ int err; + +- master = spi_alloc_master(dev, sizeof(struct altera_spi)); ++ master = devm_spi_alloc_master(dev, sizeof(struct altera_spi)); + if (!master) + return -ENOMEM; + +@@ -159,10 +159,9 @@ static int dfl_spi_altera_probe(struct dfl_device *dfl_dev) + altera_spi_init_master(master); + + err = devm_spi_register_master(dev, master); +- if (err) { +- dev_err(dev, "%s failed to register spi master %d\n", __func__, err); +- goto exit; +- } ++ if (err) ++ return dev_err_probe(dev, err, "%s failed to register spi master\n", ++ __func__); + + if (dfl_dev->revision == FME_FEATURE_REV_MAX10_SPI_N5010) + strscpy(board_info.modalias, "m10-n5010", SPI_NAME_SIZE); +@@ -179,9 +178,6 @@ static int dfl_spi_altera_probe(struct dfl_device *dfl_dev) + } + + return 0; +-exit: +- spi_master_put(master); +- return err; + } + + static const struct dfl_device_id dfl_spi_altera_ids[] = { +diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c +index d575c935e9f09..f634a405382cb 100644 +--- a/drivers/spi/spi-rspi.c ++++ b/drivers/spi/spi-rspi.c +@@ -612,6 +612,10 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, + rspi->dma_callbacked, HZ); + if (ret > 0 && rspi->dma_callbacked) { + ret = 0; ++ if (tx) ++ dmaengine_synchronize(rspi->ctlr->dma_tx); ++ if (rx) ++ dmaengine_synchronize(rspi->ctlr->dma_rx); + } else { + if (!ret) { + dev_err(&rspi->ctlr->dev, "DMA timeout\n"); +diff --git a/drivers/spi/spi-synquacer.c b/drivers/spi/spi-synquacer.c +index ea706d9629cb1..47cbe73137c23 100644 +--- a/drivers/spi/spi-synquacer.c ++++ b/drivers/spi/spi-synquacer.c +@@ -783,6 +783,7 @@ static int __maybe_unused synquacer_spi_resume(struct device *dev) + + ret = synquacer_spi_enable(master); + if (ret) { ++ clk_disable_unprepare(sspi->clk); + dev_err(dev, "failed to enable spi (%d)\n", ret); + return ret; + } +diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c +index 3b44ca455049d..cf61bf302a059 100644 +--- a/drivers/spi/spi-tegra20-slink.c ++++ b/drivers/spi/spi-tegra20-slink.c +@@ -1130,7 +1130,7 @@ exit_free_master: + + static int tegra_slink_remove(struct platform_device *pdev) + { +- struct spi_master *master = platform_get_drvdata(pdev); ++ struct spi_master *master = spi_master_get(platform_get_drvdata(pdev)); + struct tegra_slink_data *tspi = spi_master_get_devdata(master); + + spi_unregister_master(master); +@@ -1145,6 +1145,7 @@ static int tegra_slink_remove(struct platform_device *pdev) + if (tspi->rx_dma_chan) + tegra_slink_deinit_dma_param(tspi, true); + ++ spi_master_put(master); + return 0; + } + +diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c +index d0bbf8f9414d4..556d65af5e239 100644 +--- a/drivers/spi/spi.c ++++ b/drivers/spi/spi.c +@@ -2949,9 +2949,9 @@ free_bus_id: + } + EXPORT_SYMBOL_GPL(spi_register_controller); + +-static void devm_spi_unregister(void *ctlr) ++static void devm_spi_unregister(struct device *dev, void *res) + { +- spi_unregister_controller(ctlr); ++ spi_unregister_controller(*(struct spi_controller **)res); + } + + /** +@@ -2970,13 +2970,22 @@ static void devm_spi_unregister(void *ctlr) + int devm_spi_register_controller(struct device *dev, + struct spi_controller *ctlr) + { ++ struct spi_controller **ptr; + int ret; + ++ ptr = devres_alloc(devm_spi_unregister, sizeof(*ptr), GFP_KERNEL); ++ if (!ptr) ++ return -ENOMEM; ++ + ret = spi_register_controller(ctlr); +- if (ret) +- return ret; ++ if (!ret) { ++ *ptr = ctlr; ++ devres_add(dev, ptr); ++ } else { ++ devres_free(ptr); ++ } + +- return devm_add_action_or_reset(dev, devm_spi_unregister, ctlr); ++ return ret; + } + EXPORT_SYMBOL_GPL(devm_spi_register_controller); + +diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c +index ef0b0963cf930..88db9818e0839 100644 +--- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c ++++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c +@@ -899,9 +899,9 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error, + int err; + unsigned long irqflags; + struct ia_css_frame *frame = NULL; +- struct atomisp_s3a_buf *s3a_buf = NULL, *_s3a_buf_tmp; +- struct atomisp_dis_buf *dis_buf = NULL, *_dis_buf_tmp; +- struct atomisp_metadata_buf *md_buf = NULL, *_md_buf_tmp; ++ struct atomisp_s3a_buf *s3a_buf = NULL, *_s3a_buf_tmp, *s3a_iter; ++ struct atomisp_dis_buf *dis_buf = NULL, *_dis_buf_tmp, *dis_iter; ++ struct atomisp_metadata_buf *md_buf = NULL, *_md_buf_tmp, *md_iter; + enum atomisp_metadata_type md_type; + struct atomisp_device *isp = asd->isp; + struct v4l2_control ctrl; +@@ -940,60 +940,75 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error, + + switch (buf_type) { + case IA_CSS_BUFFER_TYPE_3A_STATISTICS: +- list_for_each_entry_safe(s3a_buf, _s3a_buf_tmp, ++ list_for_each_entry_safe(s3a_iter, _s3a_buf_tmp, + &asd->s3a_stats_in_css, list) { +- if (s3a_buf->s3a_data == ++ if (s3a_iter->s3a_data == + buffer.css_buffer.data.stats_3a) { +- list_del_init(&s3a_buf->list); +- list_add_tail(&s3a_buf->list, ++ list_del_init(&s3a_iter->list); ++ list_add_tail(&s3a_iter->list, + &asd->s3a_stats_ready); ++ s3a_buf = s3a_iter; + break; + } + } + + asd->s3a_bufs_in_css[css_pipe_id]--; + atomisp_3a_stats_ready_event(asd, buffer.css_buffer.exp_id); +- dev_dbg(isp->dev, "%s: s3a stat with exp_id %d is ready\n", +- __func__, s3a_buf->s3a_data->exp_id); ++ if (s3a_buf) ++ dev_dbg(isp->dev, "%s: s3a stat with exp_id %d is ready\n", ++ __func__, s3a_buf->s3a_data->exp_id); ++ else ++ dev_dbg(isp->dev, "%s: s3a stat is ready with no exp_id found\n", ++ __func__); + break; + case IA_CSS_BUFFER_TYPE_METADATA: + if (error) + break; + + md_type = atomisp_get_metadata_type(asd, css_pipe_id); +- list_for_each_entry_safe(md_buf, _md_buf_tmp, ++ list_for_each_entry_safe(md_iter, _md_buf_tmp, + &asd->metadata_in_css[md_type], list) { +- if (md_buf->metadata == ++ if (md_iter->metadata == + buffer.css_buffer.data.metadata) { +- list_del_init(&md_buf->list); +- list_add_tail(&md_buf->list, ++ list_del_init(&md_iter->list); ++ list_add_tail(&md_iter->list, + &asd->metadata_ready[md_type]); ++ md_buf = md_iter; + break; + } + } + asd->metadata_bufs_in_css[stream_id][css_pipe_id]--; + atomisp_metadata_ready_event(asd, md_type); +- dev_dbg(isp->dev, "%s: metadata with exp_id %d is ready\n", +- __func__, md_buf->metadata->exp_id); ++ if (md_buf) ++ dev_dbg(isp->dev, "%s: metadata with exp_id %d is ready\n", ++ __func__, md_buf->metadata->exp_id); ++ else ++ dev_dbg(isp->dev, "%s: metadata is ready with no exp_id found\n", ++ __func__); + break; + case IA_CSS_BUFFER_TYPE_DIS_STATISTICS: +- list_for_each_entry_safe(dis_buf, _dis_buf_tmp, ++ list_for_each_entry_safe(dis_iter, _dis_buf_tmp, + &asd->dis_stats_in_css, list) { +- if (dis_buf->dis_data == ++ if (dis_iter->dis_data == + buffer.css_buffer.data.stats_dvs) { + spin_lock_irqsave(&asd->dis_stats_lock, + irqflags); +- list_del_init(&dis_buf->list); +- list_add(&dis_buf->list, &asd->dis_stats); ++ list_del_init(&dis_iter->list); ++ list_add(&dis_iter->list, &asd->dis_stats); + asd->params.dis_proj_data_valid = true; + spin_unlock_irqrestore(&asd->dis_stats_lock, + irqflags); ++ dis_buf = dis_iter; + break; + } + } + asd->dis_bufs_in_css--; +- dev_dbg(isp->dev, "%s: dis stat with exp_id %d is ready\n", +- __func__, dis_buf->dis_data->exp_id); ++ if (dis_buf) ++ dev_dbg(isp->dev, "%s: dis stat with exp_id %d is ready\n", ++ __func__, dis_buf->dis_data->exp_id); ++ else ++ dev_dbg(isp->dev, "%s: dis stat is ready with no exp_id found\n", ++ __func__); + break; + case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME: + case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME: +diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h +index c2e2dca38628a..88792c863edc1 100644 +--- a/drivers/staging/media/hantro/hantro.h ++++ b/drivers/staging/media/hantro/hantro.h +@@ -262,6 +262,7 @@ struct hantro_ctx { + * @max_depth: Maximum depth, for bitstream formats + * @enc_fmt: Format identifier for encoder registers. + * @frmsize: Supported range of frame sizes (only for bitstream formats). ++ * @postprocessed: Indicates if this format needs the post-processor. + */ + struct hantro_fmt { + char *name; +@@ -271,6 +272,7 @@ struct hantro_fmt { + int max_depth; + enum hantro_enc_fmt enc_fmt; + struct v4l2_frmsize_stepwise frmsize; ++ bool postprocessed; + }; + + struct hantro_reg { +diff --git a/drivers/staging/media/hantro/hantro_g2_hevc_dec.c b/drivers/staging/media/hantro/hantro_g2_hevc_dec.c +index e63b777d42660..bcdfa359de7f1 100644 +--- a/drivers/staging/media/hantro/hantro_g2_hevc_dec.c ++++ b/drivers/staging/media/hantro/hantro_g2_hevc_dec.c +@@ -264,24 +264,11 @@ static void set_params(struct hantro_ctx *ctx) + hantro_reg_write(vpu, &g2_apf_threshold, 8); + } + +-static int find_ref_pic_index(const struct v4l2_hevc_dpb_entry *dpb, int pic_order_cnt) +-{ +- int i; +- +- for (i = 0; i < V4L2_HEVC_DPB_ENTRIES_NUM_MAX; i++) { +- if (dpb[i].pic_order_cnt[0] == pic_order_cnt) +- return i; +- } +- +- return 0x0; +-} +- + static void set_ref_pic_list(struct hantro_ctx *ctx) + { + const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls; + struct hantro_dev *vpu = ctx->dev; + const struct v4l2_ctrl_hevc_decode_params *decode_params = ctrls->decode_params; +- const struct v4l2_hevc_dpb_entry *dpb = decode_params->dpb; + u32 list0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX] = {}; + u32 list1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX] = {}; + static const struct hantro_reg ref_pic_regs0[] = { +@@ -325,11 +312,11 @@ static void set_ref_pic_list(struct hantro_ctx *ctx) + /* List 0 contains: short term before, short term after and long term */ + j = 0; + for (i = 0; i < decode_params->num_poc_st_curr_before && j < ARRAY_SIZE(list0); i++) +- list0[j++] = find_ref_pic_index(dpb, decode_params->poc_st_curr_before[i]); ++ list0[j++] = decode_params->poc_st_curr_before[i]; + for (i = 0; i < decode_params->num_poc_st_curr_after && j < ARRAY_SIZE(list0); i++) +- list0[j++] = find_ref_pic_index(dpb, decode_params->poc_st_curr_after[i]); ++ list0[j++] = decode_params->poc_st_curr_after[i]; + for (i = 0; i < decode_params->num_poc_lt_curr && j < ARRAY_SIZE(list0); i++) +- list0[j++] = find_ref_pic_index(dpb, decode_params->poc_lt_curr[i]); ++ list0[j++] = decode_params->poc_lt_curr[i]; + + /* Fill the list, copying over and over */ + i = 0; +@@ -338,11 +325,11 @@ static void set_ref_pic_list(struct hantro_ctx *ctx) + + j = 0; + for (i = 0; i < decode_params->num_poc_st_curr_after && j < ARRAY_SIZE(list1); i++) +- list1[j++] = find_ref_pic_index(dpb, decode_params->poc_st_curr_after[i]); ++ list1[j++] = decode_params->poc_st_curr_after[i]; + for (i = 0; i < decode_params->num_poc_st_curr_before && j < ARRAY_SIZE(list1); i++) +- list1[j++] = find_ref_pic_index(dpb, decode_params->poc_st_curr_before[i]); ++ list1[j++] = decode_params->poc_st_curr_before[i]; + for (i = 0; i < decode_params->num_poc_lt_curr && j < ARRAY_SIZE(list1); i++) +- list1[j++] = find_ref_pic_index(dpb, decode_params->poc_lt_curr[i]); ++ list1[j++] = decode_params->poc_lt_curr[i]; + + i = 0; + while (j < ARRAY_SIZE(list1)) +@@ -426,7 +413,7 @@ static int set_ref(struct hantro_ctx *ctx) + + set_ref_pic_list(ctx); + +- /* We will only keep the references picture that are still used */ ++ /* We will only keep the reference pictures that are still used */ + ctx->hevc_dec.ref_bufs_used = 0; + + /* Set up addresses of DPB buffers */ +diff --git a/drivers/staging/media/hantro/hantro_hevc.c b/drivers/staging/media/hantro/hantro_hevc.c +index 5347f5a41c2ac..7ce98a2b16558 100644 +--- a/drivers/staging/media/hantro/hantro_hevc.c ++++ b/drivers/staging/media/hantro/hantro_hevc.c +@@ -98,7 +98,7 @@ dma_addr_t hantro_hevc_get_ref_buf(struct hantro_ctx *ctx, + struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec; + int i; + +- /* Find the reference buffer in already know ones */ ++ /* Find the reference buffer in already known ones */ + for (i = 0; i < NUM_REF_PICTURES; i++) { + if (hevc_dec->ref_bufs_poc[i] == poc) { + hevc_dec->ref_bufs_used |= 1 << i; +diff --git a/drivers/staging/media/hantro/hantro_postproc.c b/drivers/staging/media/hantro/hantro_postproc.c +index ed8916c950a4f..46434c97317bd 100644 +--- a/drivers/staging/media/hantro/hantro_postproc.c ++++ b/drivers/staging/media/hantro/hantro_postproc.c +@@ -53,15 +53,9 @@ const struct hantro_postproc_regs hantro_g1_postproc_regs = { + bool hantro_needs_postproc(const struct hantro_ctx *ctx, + const struct hantro_fmt *fmt) + { +- struct hantro_dev *vpu = ctx->dev; +- + if (ctx->is_encoder) + return false; +- +- if (!vpu->variant->postproc_fmts) +- return false; +- +- return fmt->fourcc != V4L2_PIX_FMT_NV12; ++ return fmt->postprocessed; + } + + void hantro_postproc_enable(struct hantro_ctx *ctx) +@@ -132,9 +126,10 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx) + unsigned int num_buffers = cap_queue->num_buffers; + unsigned int i, buf_size; + +- buf_size = ctx->dst_fmt.plane_fmt[0].sizeimage + +- hantro_h264_mv_size(ctx->dst_fmt.width, +- ctx->dst_fmt.height); ++ buf_size = ctx->dst_fmt.plane_fmt[0].sizeimage; ++ if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_H264_SLICE) ++ buf_size += hantro_h264_mv_size(ctx->dst_fmt.width, ++ ctx->dst_fmt.height); + + for (i = 0; i < num_buffers; ++i) { + struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i]; +diff --git a/drivers/staging/media/hantro/imx8m_vpu_hw.c b/drivers/staging/media/hantro/imx8m_vpu_hw.c +index ea919bfb9891a..b692b74b09149 100644 +--- a/drivers/staging/media/hantro/imx8m_vpu_hw.c ++++ b/drivers/staging/media/hantro/imx8m_vpu_hw.c +@@ -82,6 +82,7 @@ static const struct hantro_fmt imx8m_vpu_postproc_fmts[] = { + { + .fourcc = V4L2_PIX_FMT_YUYV, + .codec_mode = HANTRO_MODE_NONE, ++ .postprocessed = true, + }, + }; + +diff --git a/drivers/staging/media/hantro/rockchip_vpu_hw.c b/drivers/staging/media/hantro/rockchip_vpu_hw.c +index 0c22039162a00..543dc4a5486c0 100644 +--- a/drivers/staging/media/hantro/rockchip_vpu_hw.c ++++ b/drivers/staging/media/hantro/rockchip_vpu_hw.c +@@ -62,6 +62,7 @@ static const struct hantro_fmt rockchip_vpu1_postproc_fmts[] = { + { + .fourcc = V4L2_PIX_FMT_YUYV, + .codec_mode = HANTRO_MODE_NONE, ++ .postprocessed = true, + }, + }; + +diff --git a/drivers/staging/media/hantro/sama5d4_vdec_hw.c b/drivers/staging/media/hantro/sama5d4_vdec_hw.c +index 9c3b8cd0b2394..99432008b2414 100644 +--- a/drivers/staging/media/hantro/sama5d4_vdec_hw.c ++++ b/drivers/staging/media/hantro/sama5d4_vdec_hw.c +@@ -15,6 +15,7 @@ static const struct hantro_fmt sama5d4_vdec_postproc_fmts[] = { + { + .fourcc = V4L2_PIX_FMT_YUYV, + .codec_mode = HANTRO_MODE_NONE, ++ .postprocessed = true, + }, + }; + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +index 754942ecf064c..830cae03fc6e4 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -147,6 +147,9 @@ static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx, + dpb[i].pic_order_cnt[1] + }; + ++ if (buffer_index < 0) ++ continue; ++ + cedrus_h265_frame_info_write_single(ctx, i, dpb[i].field_pic, + pic_order_cnt, + buffer_index); +@@ -495,7 +498,6 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + + reg = VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_TC_OFFSET_DIV2(slice_params->slice_tc_offset_div2) | + VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_BETA_OFFSET_DIV2(slice_params->slice_beta_offset_div2) | +- VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_POC_BIGEST_IN_RPS_ST(decode_params->num_poc_st_curr_after == 0) | + VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CR_QP_OFFSET(slice_params->slice_cr_qp_offset) | + VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CB_QP_OFFSET(slice_params->slice_cb_qp_offset) | + VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_QP_DELTA(slice_params->slice_qp_delta); +@@ -508,6 +510,9 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, + V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED, + slice_params->flags); + ++ if (decode_params->num_poc_st_curr_after == 0) ++ reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO1_FLAG_SLICE_NOT_LOW_DELAY; ++ + cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO1, reg); + + chroma_log2_weight_denom = pred_weight_table->luma_log2_weight_denom + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +index 92ace87c1c7d1..5f34e36702893 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +@@ -377,13 +377,12 @@ + + #define VE_DEC_H265_DEC_SLICE_HDR_INFO1_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED BIT(23) + #define VE_DEC_H265_DEC_SLICE_HDR_INFO1_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED BIT(22) ++#define VE_DEC_H265_DEC_SLICE_HDR_INFO1_FLAG_SLICE_NOT_LOW_DELAY BIT(21) + + #define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_TC_OFFSET_DIV2(v) \ + SHIFT_AND_MASK_BITS(v, 31, 28) + #define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_BETA_OFFSET_DIV2(v) \ + SHIFT_AND_MASK_BITS(v, 27, 24) +-#define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_POC_BIGEST_IN_RPS_ST(v) \ +- ((v) ? BIT(21) : 0) + #define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CR_QP_OFFSET(v) \ + SHIFT_AND_MASK_BITS(v, 20, 16) + #define VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CB_QP_OFFSET(v) \ +diff --git a/drivers/staging/rtl8192u/r8192U.h b/drivers/staging/rtl8192u/r8192U.h +index 4013107cd93a2..a23d6d41de9d4 100644 +--- a/drivers/staging/rtl8192u/r8192U.h ++++ b/drivers/staging/rtl8192u/r8192U.h +@@ -1013,7 +1013,7 @@ typedef struct r8192_priv { + bool bis_any_nonbepkts; + bool bcurrent_turbo_EDCA; + bool bis_cur_rdlstate; +- struct timer_list fsync_timer; ++ struct delayed_work fsync_work; + bool bfsync_processing; /* 500ms Fsync timer is active or not */ + u32 rate_record; + u32 rateCountDiffRecord; +diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c +index 725bf5ca9e34d..0fcfcaa6500bf 100644 +--- a/drivers/staging/rtl8192u/r8192U_dm.c ++++ b/drivers/staging/rtl8192u/r8192U_dm.c +@@ -2578,19 +2578,20 @@ static void dm_init_fsync(struct net_device *dev) + priv->ieee80211->fsync_seconddiff_ratethreshold = 200; + priv->ieee80211->fsync_state = Default_Fsync; + priv->framesyncMonitor = 1; /* current default 0xc38 monitor on */ +- timer_setup(&priv->fsync_timer, dm_fsync_timer_callback, 0); ++ INIT_DELAYED_WORK(&priv->fsync_work, dm_fsync_work_callback); + } + + static void dm_deInit_fsync(struct net_device *dev) + { + struct r8192_priv *priv = ieee80211_priv(dev); + +- del_timer_sync(&priv->fsync_timer); ++ cancel_delayed_work_sync(&priv->fsync_work); + } + +-void dm_fsync_timer_callback(struct timer_list *t) ++void dm_fsync_work_callback(struct work_struct *work) + { +- struct r8192_priv *priv = from_timer(priv, t, fsync_timer); ++ struct r8192_priv *priv = ++ container_of(work, struct r8192_priv, fsync_work.work); + struct net_device *dev = priv->ieee80211->dev; + u32 rate_index, rate_count = 0, rate_count_diff = 0; + bool bSwitchFromCountDiff = false; +@@ -2657,17 +2658,16 @@ void dm_fsync_timer_callback(struct timer_list *t) + } + } + if (bDoubleTimeInterval) { +- if (timer_pending(&priv->fsync_timer)) +- del_timer_sync(&priv->fsync_timer); +- priv->fsync_timer.expires = jiffies + +- msecs_to_jiffies(priv->ieee80211->fsync_time_interval*priv->ieee80211->fsync_multiple_timeinterval); +- add_timer(&priv->fsync_timer); ++ cancel_delayed_work_sync(&priv->fsync_work); ++ schedule_delayed_work(&priv->fsync_work, ++ msecs_to_jiffies(priv ++ ->ieee80211->fsync_time_interval * ++ priv->ieee80211->fsync_multiple_timeinterval)); + } else { +- if (timer_pending(&priv->fsync_timer)) +- del_timer_sync(&priv->fsync_timer); +- priv->fsync_timer.expires = jiffies + +- msecs_to_jiffies(priv->ieee80211->fsync_time_interval); +- add_timer(&priv->fsync_timer); ++ cancel_delayed_work_sync(&priv->fsync_work); ++ schedule_delayed_work(&priv->fsync_work, ++ msecs_to_jiffies(priv ++ ->ieee80211->fsync_time_interval)); + } + } else { + /* Let Register return to default value; */ +@@ -2695,7 +2695,7 @@ static void dm_EndSWFsync(struct net_device *dev) + struct r8192_priv *priv = ieee80211_priv(dev); + + RT_TRACE(COMP_HALDM, "%s\n", __func__); +- del_timer_sync(&(priv->fsync_timer)); ++ cancel_delayed_work_sync(&priv->fsync_work); + + /* Let Register return to default value; */ + if (priv->bswitch_fsync) { +@@ -2736,11 +2736,9 @@ static void dm_StartSWFsync(struct net_device *dev) + if (priv->ieee80211->fsync_rate_bitmap & rateBitmap) + priv->rate_record += priv->stats.received_rate_histogram[1][rateIndex]; + } +- if (timer_pending(&priv->fsync_timer)) +- del_timer_sync(&priv->fsync_timer); +- priv->fsync_timer.expires = jiffies + +- msecs_to_jiffies(priv->ieee80211->fsync_time_interval); +- add_timer(&priv->fsync_timer); ++ cancel_delayed_work_sync(&priv->fsync_work); ++ schedule_delayed_work(&priv->fsync_work, ++ msecs_to_jiffies(priv->ieee80211->fsync_time_interval)); + + write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cd); + } +diff --git a/drivers/staging/rtl8192u/r8192U_dm.h b/drivers/staging/rtl8192u/r8192U_dm.h +index 0b2a1c688597c..2159018b4e38f 100644 +--- a/drivers/staging/rtl8192u/r8192U_dm.h ++++ b/drivers/staging/rtl8192u/r8192U_dm.h +@@ -166,7 +166,7 @@ void dm_force_tx_fw_info(struct net_device *dev, + void dm_init_edca_turbo(struct net_device *dev); + void dm_rf_operation_test_callback(unsigned long data); + void dm_rf_pathcheck_workitemcallback(struct work_struct *work); +-void dm_fsync_timer_callback(struct timer_list *t); ++void dm_fsync_work_callback(struct work_struct *work); + void dm_cck_txpower_adjust(struct net_device *dev, bool binch14); + void dm_shadow_init(struct net_device *dev); + void dm_initialize_txpower_tracking(struct net_device *dev); +diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c +index 1c4aac8464a70..1e5a78131aba9 100644 +--- a/drivers/thermal/thermal_sysfs.c ++++ b/drivers/thermal/thermal_sysfs.c +@@ -813,12 +813,13 @@ static const struct attribute_group cooling_device_stats_attr_group = { + + static void cooling_device_stats_setup(struct thermal_cooling_device *cdev) + { ++ const struct attribute_group *stats_attr_group = NULL; + struct cooling_dev_stats *stats; + unsigned long states; + int var; + + if (cdev->ops->get_max_state(cdev, &states)) +- return; ++ goto out; + + states++; /* Total number of states is highest state + 1 */ + +@@ -828,7 +829,7 @@ static void cooling_device_stats_setup(struct thermal_cooling_device *cdev) + + stats = kzalloc(var, GFP_KERNEL); + if (!stats) +- return; ++ goto out; + + stats->time_in_state = (ktime_t *)(stats + 1); + stats->trans_table = (unsigned int *)(stats->time_in_state + states); +@@ -838,9 +839,12 @@ static void cooling_device_stats_setup(struct thermal_cooling_device *cdev) + + spin_lock_init(&stats->lock); + ++ stats_attr_group = &cooling_device_stats_attr_group; ++ ++out: + /* Fill the empty slot left in cooling_device_attr_groups */ + var = ARRAY_SIZE(cooling_device_attr_groups) - 2; +- cooling_device_attr_groups[var] = &cooling_device_stats_attr_group; ++ cooling_device_attr_groups[var] = stats_attr_group; + } + + static void cooling_device_stats_destroy(struct thermal_cooling_device *cdev) +diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c +index 4946a241e323f..b89655f585f14 100644 +--- a/drivers/tty/n_gsm.c ++++ b/drivers/tty/n_gsm.c +@@ -235,6 +235,7 @@ struct gsm_mux { + struct gsm_dlci *dlci[NUM_DLCI]; + int old_c_iflag; /* termios c_iflag value before attach */ + bool constipated; /* Asked by remote to shut up */ ++ bool has_devices; /* Devices were registered */ + + spinlock_t tx_lock; + unsigned int tx_bytes; /* TX data outstanding */ +@@ -243,6 +244,7 @@ struct gsm_mux { + struct list_head tx_list; /* Pending data packets */ + + /* Control messages */ ++ struct timer_list kick_timer; /* Kick TX queuing on timeout */ + struct timer_list t2_timer; /* Retransmit timer for commands */ + int cretries; /* Command retry counter */ + struct gsm_control *pending_cmd;/* Our current pending command */ +@@ -423,6 +425,27 @@ static int gsm_read_ea(unsigned int *val, u8 c) + return c & EA; + } + ++/** ++ * gsm_read_ea_val - read a value until EA ++ * @val: variable holding value ++ * @data: buffer of data ++ * @dlen: length of data ++ * ++ * Processes an EA value. Updates the passed variable and ++ * returns the processed data length. ++ */ ++static unsigned int gsm_read_ea_val(unsigned int *val, const u8 *data, int dlen) ++{ ++ unsigned int len = 0; ++ ++ for (; dlen > 0; dlen--) { ++ len++; ++ if (gsm_read_ea(val, *data++)) ++ break; ++ } ++ return len; ++} ++ + /** + * gsm_encode_modem - encode modem data bits + * @dlci: DLCI to encode from +@@ -467,6 +490,68 @@ static void gsm_hex_dump_bytes(const char *fname, const u8 *data, + kfree(prefix); + } + ++/** ++ * gsm_register_devices - register all tty devices for a given mux index ++ * ++ * @driver: the tty driver that describes the tty devices ++ * @index: the mux number is used to calculate the minor numbers of the ++ * ttys for this mux and may differ from the position in the ++ * mux array. ++ */ ++static int gsm_register_devices(struct tty_driver *driver, unsigned int index) ++{ ++ struct device *dev; ++ int i; ++ unsigned int base; ++ ++ if (!driver || index >= MAX_MUX) ++ return -EINVAL; ++ ++ base = index * NUM_DLCI; /* first minor for this index */ ++ for (i = 1; i < NUM_DLCI; i++) { ++ /* Don't register device 0 - this is the control channel ++ * and not a usable tty interface ++ */ ++ dev = tty_register_device(gsm_tty_driver, base + i, NULL); ++ if (IS_ERR(dev)) { ++ if (debug & 8) ++ pr_info("%s failed to register device minor %u", ++ __func__, base + i); ++ for (i--; i >= 1; i--) ++ tty_unregister_device(gsm_tty_driver, base + i); ++ return PTR_ERR(dev); ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * gsm_unregister_devices - unregister all tty devices for a given mux index ++ * ++ * @driver: the tty driver that describes the tty devices ++ * @index: the mux number is used to calculate the minor numbers of the ++ * ttys for this mux and may differ from the position in the ++ * mux array. ++ */ ++static void gsm_unregister_devices(struct tty_driver *driver, ++ unsigned int index) ++{ ++ int i; ++ unsigned int base; ++ ++ if (!driver || index >= MAX_MUX) ++ return; ++ ++ base = index * NUM_DLCI; /* first minor for this index */ ++ for (i = 1; i < NUM_DLCI; i++) { ++ /* Don't unregister device 0 - this is the control ++ * channel and not a usable tty interface ++ */ ++ tty_unregister_device(gsm_tty_driver, base + i); ++ } ++} ++ + /** + * gsm_print_packet - display a frame for debug + * @hdr: header to print before decode +@@ -682,6 +767,37 @@ static struct gsm_msg *gsm_data_alloc(struct gsm_mux *gsm, u8 addr, int len, + return m; + } + ++/** ++ * gsm_is_flow_ctrl_msg - checks if flow control message ++ * @msg: message to check ++ * ++ * Returns true if the given message is a flow control command of the ++ * control channel. False is returned in any other case. ++ */ ++static bool gsm_is_flow_ctrl_msg(struct gsm_msg *msg) ++{ ++ unsigned int cmd; ++ ++ if (msg->addr > 0) ++ return false; ++ ++ switch (msg->ctrl & ~PF) { ++ case UI: ++ case UIH: ++ cmd = 0; ++ if (gsm_read_ea_val(&cmd, msg->data + 2, msg->len - 2) < 1) ++ break; ++ switch (cmd & ~PF) { ++ case CMD_FCOFF: ++ case CMD_FCON: ++ return true; ++ } ++ break; ++ } ++ ++ return false; ++} ++ + /** + * gsm_data_kick - poke the queue + * @gsm: GSM Mux +@@ -701,7 +817,7 @@ static void gsm_data_kick(struct gsm_mux *gsm, struct gsm_dlci *dlci) + int len; + + list_for_each_entry_safe(msg, nmsg, &gsm->tx_list, list) { +- if (gsm->constipated && msg->addr) ++ if (gsm->constipated && !gsm_is_flow_ctrl_msg(msg)) + continue; + if (gsm->encoding != 0) { + gsm->txframe[0] = GSM1_SOF; +@@ -787,6 +903,7 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg) + list_add_tail(&msg->list, &gsm->tx_list); + gsm->tx_bytes += msg->len; + gsm_data_kick(gsm, dlci); ++ mod_timer(&gsm->kick_timer, jiffies + 10 * gsm->t1 * HZ / 100); + } + + /** +@@ -823,41 +940,48 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci) + { + struct gsm_msg *msg; + u8 *dp; +- int len, total_size, size; +- int h = dlci->adaption - 1; ++ int h, len, size; + +- total_size = 0; +- while (1) { +- len = kfifo_len(&dlci->fifo); +- if (len == 0) +- return total_size; +- +- /* MTU/MRU count only the data bits */ +- if (len > gsm->mtu) +- len = gsm->mtu; +- +- size = len + h; +- +- msg = gsm_data_alloc(gsm, dlci->addr, size, gsm->ftype); +- /* FIXME: need a timer or something to kick this so it can't +- get stuck with no work outstanding and no buffer free */ +- if (msg == NULL) +- return -ENOMEM; +- dp = msg->data; +- switch (dlci->adaption) { +- case 1: /* Unstructured */ +- break; +- case 2: /* Unstructed with modem bits. +- Always one byte as we never send inline break data */ +- *dp++ = (gsm_encode_modem(dlci) << 1) | EA; +- break; +- } +- WARN_ON(kfifo_out_locked(&dlci->fifo, dp , len, &dlci->lock) != len); +- __gsm_data_queue(dlci, msg); +- total_size += size; ++ /* for modem bits without break data */ ++ h = ((dlci->adaption == 1) ? 0 : 1); ++ ++ len = kfifo_len(&dlci->fifo); ++ if (len == 0) ++ return 0; ++ ++ /* MTU/MRU count only the data bits but watch adaption mode */ ++ if ((len + h) > gsm->mtu) ++ len = gsm->mtu - h; ++ ++ size = len + h; ++ ++ msg = gsm_data_alloc(gsm, dlci->addr, size, gsm->ftype); ++ if (!msg) ++ return -ENOMEM; ++ dp = msg->data; ++ switch (dlci->adaption) { ++ case 1: /* Unstructured */ ++ break; ++ case 2: /* Unstructured with modem bits. ++ * Always one byte as we never send inline break data ++ */ ++ *dp++ = (gsm_encode_modem(dlci) << 1) | EA; ++ break; ++ default: ++ pr_err("%s: unsupported adaption %d\n", __func__, ++ dlci->adaption); ++ break; + } ++ ++ WARN_ON(len != kfifo_out_locked(&dlci->fifo, dp, len, ++ &dlci->lock)); ++ ++ /* Notify upper layer about available send space. */ ++ tty_port_tty_wakeup(&dlci->port); ++ ++ __gsm_data_queue(dlci, msg); + /* Bytes of data we used up */ +- return total_size; ++ return size; + } + + /** +@@ -908,9 +1032,6 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, + + size = len + overhead; + msg = gsm_data_alloc(gsm, dlci->addr, size, gsm->ftype); +- +- /* FIXME: need a timer or something to kick this so it can't +- get stuck with no work outstanding and no buffer free */ + if (msg == NULL) { + skb_queue_tail(&dlci->skb_list, dlci->skb); + dlci->skb = NULL; +@@ -1006,9 +1127,9 @@ static int gsm_dlci_modem_output(struct gsm_mux *gsm, struct gsm_dlci *dlci, + * renegotiate DLCI priorities with optional stuff. Needs optimising. + */ + +-static void gsm_dlci_data_sweep(struct gsm_mux *gsm) ++static int gsm_dlci_data_sweep(struct gsm_mux *gsm) + { +- int len; ++ int len, ret = 0; + /* Priority ordering: We should do priority with RR of the groups */ + int i = 1; + +@@ -1031,7 +1152,11 @@ static void gsm_dlci_data_sweep(struct gsm_mux *gsm) + /* DLCI empty - try the next */ + if (len == 0) + i++; ++ else ++ ret++; + } ++ ++ return ret; + } + + /** +@@ -1421,7 +1546,7 @@ static void gsm_control_retransmit(struct timer_list *t) + spin_lock_irqsave(&gsm->control_lock, flags); + ctrl = gsm->pending_cmd; + if (ctrl) { +- if (gsm->cretries == 0) { ++ if (gsm->cretries == 0 || !gsm->dlci[0] || gsm->dlci[0]->dead) { + gsm->pending_cmd = NULL; + ctrl->error = -ETIMEDOUT; + ctrl->done = 1; +@@ -1524,6 +1649,8 @@ static void gsm_dlci_close(struct gsm_dlci *dlci) + if (debug & 8) + pr_debug("DLCI %d goes closed.\n", dlci->addr); + dlci->state = DLCI_CLOSED; ++ /* Prevent us from sending data before the link is up again */ ++ dlci->constipated = true; + if (dlci->addr != 0) { + tty_port_tty_hangup(&dlci->port, false); + spin_lock_irqsave(&dlci->lock, flags); +@@ -1553,6 +1680,7 @@ static void gsm_dlci_open(struct gsm_dlci *dlci) + del_timer(&dlci->t1); + /* This will let a tty open continue */ + dlci->state = DLCI_OPEN; ++ dlci->constipated = false; + if (debug & 8) + pr_debug("DLCI %d goes open.\n", dlci->addr); + /* Send current modem state */ +@@ -1583,8 +1711,8 @@ static void gsm_dlci_t1(struct timer_list *t) + + switch (dlci->state) { + case DLCI_OPENING: +- dlci->retries--; + if (dlci->retries) { ++ dlci->retries--; + gsm_command(dlci->gsm, dlci->addr, SABM|PF); + mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100); + } else if (!dlci->addr && gsm->control == (DM | PF)) { +@@ -1599,8 +1727,8 @@ static void gsm_dlci_t1(struct timer_list *t) + + break; + case DLCI_CLOSING: +- dlci->retries--; + if (dlci->retries) { ++ dlci->retries--; + gsm_command(dlci->gsm, dlci->addr, DISC|PF); + mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100); + } else +@@ -1633,6 +1761,25 @@ static void gsm_dlci_begin_open(struct gsm_dlci *dlci) + mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100); + } + ++/** ++ * gsm_dlci_set_opening - change state to opening ++ * @dlci: DLCI to open ++ * ++ * Change internal state to wait for DLCI open from initiator side. ++ * We set off timers and responses upon reception of an SABM. ++ */ ++static void gsm_dlci_set_opening(struct gsm_dlci *dlci) ++{ ++ switch (dlci->state) { ++ case DLCI_CLOSED: ++ case DLCI_CLOSING: ++ dlci->state = DLCI_OPENING; ++ break; ++ default: ++ break; ++ } ++} ++ + /** + * gsm_dlci_begin_close - start channel open procedure + * @dlci: DLCI to open +@@ -1742,6 +1889,30 @@ static void gsm_dlci_command(struct gsm_dlci *dlci, const u8 *data, int len) + } + } + ++/** ++ * gsm_kick_timer - transmit if possible ++ * @t: timer contained in our gsm object ++ * ++ * Transmit data from DLCIs if the queue is empty. We can't rely on ++ * a tty wakeup except when we filled the pipe so we need to fire off ++ * new data ourselves in other cases. ++ */ ++static void gsm_kick_timer(struct timer_list *t) ++{ ++ struct gsm_mux *gsm = from_timer(gsm, t, kick_timer); ++ unsigned long flags; ++ int sent = 0; ++ ++ spin_lock_irqsave(&gsm->tx_lock, flags); ++ /* If we have nothing running then we need to fire up */ ++ if (gsm->tx_bytes < TX_THRESH_LO) ++ sent = gsm_dlci_data_sweep(gsm); ++ spin_unlock_irqrestore(&gsm->tx_lock, flags); ++ ++ if (sent && debug & 4) ++ pr_info("%s TX queue stalled\n", __func__); ++} ++ + /* + * Allocate/Free DLCI channels + */ +@@ -1776,10 +1947,13 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr) + dlci->addr = addr; + dlci->adaption = gsm->adaption; + dlci->state = DLCI_CLOSED; +- if (addr) ++ if (addr) { + dlci->data = gsm_dlci_data; +- else ++ /* Prevent us from sending data before the link is up */ ++ dlci->constipated = true; ++ } else { + dlci->data = gsm_dlci_command; ++ } + gsm->dlci[addr] = dlci; + return dlci; + } +@@ -1974,7 +2148,7 @@ static void gsm_queue(struct gsm_mux *gsm) + goto invalid; + #endif + if (dlci == NULL || dlci->state != DLCI_OPEN) { +- gsm_command(gsm, address, DM|PF); ++ gsm_response(gsm, address, DM|PF); + return; + } + dlci->data(dlci, gsm->buf, gsm->len); +@@ -2228,9 +2402,14 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc) + } + + /* Finish outstanding timers, making sure they are done */ ++ del_timer_sync(&gsm->kick_timer); + del_timer_sync(&gsm->t2_timer); + + /* Free up any link layer users and finally the control channel */ ++ if (gsm->has_devices) { ++ gsm_unregister_devices(gsm_tty_driver, gsm->num); ++ gsm->has_devices = false; ++ } + for (i = NUM_DLCI - 1; i >= 0; i--) + if (gsm->dlci[i]) + gsm_dlci_release(gsm->dlci[i]); +@@ -2254,7 +2433,13 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc) + static int gsm_activate_mux(struct gsm_mux *gsm) + { + struct gsm_dlci *dlci; ++ int ret; ++ ++ dlci = gsm_dlci_alloc(gsm, 0); ++ if (dlci == NULL) ++ return -ENOMEM; + ++ timer_setup(&gsm->kick_timer, gsm_kick_timer, 0); + timer_setup(&gsm->t2_timer, gsm_control_retransmit, 0); + init_waitqueue_head(&gsm->event); + spin_lock_init(&gsm->control_lock); +@@ -2265,9 +2450,11 @@ static int gsm_activate_mux(struct gsm_mux *gsm) + else + gsm->receive = gsm1_receive; + +- dlci = gsm_dlci_alloc(gsm, 0); +- if (dlci == NULL) +- return -ENOMEM; ++ ret = gsm_register_devices(gsm_tty_driver, gsm->num); ++ if (ret) ++ return ret; ++ ++ gsm->has_devices = true; + gsm->dead = false; /* Tty opens are now permissible */ + return 0; + } +@@ -2527,39 +2714,14 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len) + * will need moving to an ioctl path. + */ + +-static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) ++static void gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) + { +- unsigned int base; +- int ret, i; +- + gsm->tty = tty_kref_get(tty); + /* Turn off tty XON/XOFF handling to handle it explicitly. */ + gsm->old_c_iflag = tty->termios.c_iflag; + tty->termios.c_iflag &= (IXON | IXOFF); +- ret = gsm_activate_mux(gsm); +- if (ret != 0) +- tty_kref_put(gsm->tty); +- else { +- /* Don't register device 0 - this is the control channel and not +- a usable tty interface */ +- base = mux_num_to_base(gsm); /* Base for this MUX */ +- for (i = 1; i < NUM_DLCI; i++) { +- struct device *dev; +- +- dev = tty_register_device(gsm_tty_driver, +- base + i, NULL); +- if (IS_ERR(dev)) { +- for (i--; i >= 1; i--) +- tty_unregister_device(gsm_tty_driver, +- base + i); +- return PTR_ERR(dev); +- } +- } +- } +- return ret; + } + +- + /** + * gsmld_detach_gsm - stop doing 0710 mux + * @tty: tty attached to the mux +@@ -2570,12 +2732,7 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) + + static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) + { +- unsigned int base = mux_num_to_base(gsm); /* Base for this MUX */ +- int i; +- + WARN_ON(tty != gsm->tty); +- for (i = 1; i < NUM_DLCI; i++) +- tty_unregister_device(gsm_tty_driver, base + i); + /* Restore tty XON/XOFF handling. */ + gsm->tty->termios.c_iflag = gsm->old_c_iflag; + tty_kref_put(gsm->tty); +@@ -2667,7 +2824,6 @@ static void gsmld_close(struct tty_struct *tty) + static int gsmld_open(struct tty_struct *tty) + { + struct gsm_mux *gsm; +- int ret; + + if (tty->ops->write == NULL) + return -EINVAL; +@@ -2683,12 +2839,12 @@ static int gsmld_open(struct tty_struct *tty) + /* Attach the initial passive connection */ + gsm->encoding = 1; + +- ret = gsmld_attach_gsm(tty, gsm); +- if (ret != 0) { +- gsm_cleanup_mux(gsm, false); +- mux_put(gsm); +- } +- return ret; ++ gsmld_attach_gsm(tty, gsm); ++ ++ timer_setup(&gsm->kick_timer, gsm_kick_timer, 0); ++ timer_setup(&gsm->t2_timer, gsm_control_retransmit, 0); ++ ++ return 0; + } + + /** +@@ -2756,11 +2912,24 @@ static ssize_t gsmld_read(struct tty_struct *tty, struct file *file, + static ssize_t gsmld_write(struct tty_struct *tty, struct file *file, + const unsigned char *buf, size_t nr) + { +- int space = tty_write_room(tty); ++ struct gsm_mux *gsm = tty->disc_data; ++ unsigned long flags; ++ int space; ++ int ret; ++ ++ if (!gsm) ++ return -ENODEV; ++ ++ ret = -ENOBUFS; ++ spin_lock_irqsave(&gsm->tx_lock, flags); ++ space = tty_write_room(tty); + if (space >= nr) +- return tty->ops->write(tty, buf, nr); +- set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); +- return -ENOBUFS; ++ ret = tty->ops->write(tty, buf, nr); ++ else ++ set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); ++ spin_unlock_irqrestore(&gsm->tx_lock, flags); ++ ++ return ret; + } + + /** +@@ -2785,12 +2954,15 @@ static __poll_t gsmld_poll(struct tty_struct *tty, struct file *file, + + poll_wait(file, &tty->read_wait, wait); + poll_wait(file, &tty->write_wait, wait); ++ ++ if (gsm->dead) ++ mask |= EPOLLHUP; + if (tty_hung_up_p(file)) + mask |= EPOLLHUP; ++ if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) ++ mask |= EPOLLHUP; + if (!tty_is_writelocked(tty) && tty_write_room(tty) > 0) + mask |= EPOLLOUT | EPOLLWRNORM; +- if (gsm->dead) +- mask |= EPOLLHUP; + return mask; + } + +@@ -3214,6 +3386,7 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp) + { + struct gsm_dlci *dlci = tty->driver_data; + struct tty_port *port = &dlci->port; ++ struct gsm_mux *gsm = dlci->gsm; + + port->count++; + tty_port_tty_set(port, tty); +@@ -3223,7 +3396,10 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp) + a DM straight back. This is ok as that will have caused a hangup */ + tty_port_set_initialized(port, 1); + /* Start sending off SABM messages */ +- gsm_dlci_begin_open(dlci); ++ if (gsm->initiator) ++ gsm_dlci_begin_open(dlci); ++ else ++ gsm_dlci_set_opening(dlci); + /* And wait for virtual carrier */ + return tty_port_block_til_ready(port, tty, filp); + } +diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h +index 6473361525d1f..b3abc29aa9270 100644 +--- a/drivers/tty/serial/8250/8250.h ++++ b/drivers/tty/serial/8250/8250.h +@@ -17,6 +17,8 @@ + struct uart_8250_dma { + int (*tx_dma)(struct uart_8250_port *p); + int (*rx_dma)(struct uart_8250_port *p); ++ void (*prepare_tx_dma)(struct uart_8250_port *p); ++ void (*prepare_rx_dma)(struct uart_8250_port *p); + + /* Filter function */ + dma_filter_fn fn; +@@ -120,6 +122,28 @@ static inline void serial_out(struct uart_8250_port *up, int offset, int value) + up->port.serial_out(&up->port, offset, value); + } + ++/* ++ * For the 16C950 ++ */ ++static void serial_icr_write(struct uart_8250_port *up, int offset, int value) ++{ ++ serial_out(up, UART_SCR, offset); ++ serial_out(up, UART_ICR, value); ++} ++ ++static unsigned int __maybe_unused serial_icr_read(struct uart_8250_port *up, ++ int offset) ++{ ++ unsigned int value; ++ ++ serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD); ++ serial_out(up, UART_SCR, offset); ++ value = serial_in(up, UART_ICR); ++ serial_icr_write(up, UART_ACR, up->acr); ++ ++ return value; ++} ++ + void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p); + + static inline int serial_dl_read(struct uart_8250_port *up) +@@ -309,6 +333,22 @@ extern int serial8250_rx_dma(struct uart_8250_port *); + extern void serial8250_rx_dma_flush(struct uart_8250_port *); + extern int serial8250_request_dma(struct uart_8250_port *); + extern void serial8250_release_dma(struct uart_8250_port *); ++ ++static inline void serial8250_do_prepare_tx_dma(struct uart_8250_port *p) ++{ ++ struct uart_8250_dma *dma = p->dma; ++ ++ if (dma->prepare_tx_dma) ++ dma->prepare_tx_dma(p); ++} ++ ++static inline void serial8250_do_prepare_rx_dma(struct uart_8250_port *p) ++{ ++ struct uart_8250_dma *dma = p->dma; ++ ++ if (dma->prepare_rx_dma) ++ dma->prepare_rx_dma(p); ++} + #else + static inline int serial8250_tx_dma(struct uart_8250_port *p) + { +diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c +index 0877cf24f7de0..711cf30e835aa 100644 +--- a/drivers/tty/serial/8250/8250_bcm7271.c ++++ b/drivers/tty/serial/8250/8250_bcm7271.c +@@ -1141,16 +1141,19 @@ static int __maybe_unused brcmuart_suspend(struct device *dev) + struct brcmuart_priv *priv = dev_get_drvdata(dev); + struct uart_8250_port *up = serial8250_get_port(priv->line); + struct uart_port *port = &up->port; +- +- serial8250_suspend_port(priv->line); +- clk_disable_unprepare(priv->baud_mux_clk); ++ unsigned long flags; + + /* + * This will prevent resume from enabling RTS before the +- * baud rate has been resored. ++ * baud rate has been restored. + */ ++ spin_lock_irqsave(&port->lock, flags); + priv->saved_mctrl = port->mctrl; +- port->mctrl = 0; ++ port->mctrl &= ~TIOCM_RTS; ++ spin_unlock_irqrestore(&port->lock, flags); ++ ++ serial8250_suspend_port(priv->line); ++ clk_disable_unprepare(priv->baud_mux_clk); + + return 0; + } +@@ -1160,6 +1163,7 @@ static int __maybe_unused brcmuart_resume(struct device *dev) + struct brcmuart_priv *priv = dev_get_drvdata(dev); + struct uart_8250_port *up = serial8250_get_port(priv->line); + struct uart_port *port = &up->port; ++ unsigned long flags; + int ret; + + ret = clk_prepare_enable(priv->baud_mux_clk); +@@ -1182,7 +1186,15 @@ static int __maybe_unused brcmuart_resume(struct device *dev) + start_rx_dma(serial8250_get_port(priv->line)); + } + serial8250_resume_port(priv->line); +- port->mctrl = priv->saved_mctrl; ++ ++ if (priv->saved_mctrl & TIOCM_RTS) { ++ /* Restore RTS */ ++ spin_lock_irqsave(&port->lock, flags); ++ port->mctrl |= TIOCM_RTS; ++ port->ops->set_mctrl(port, port->mctrl); ++ spin_unlock_irqrestore(&port->lock, flags); ++ } ++ + return 0; + } + +diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c +index b3c3f7e5851ab..1bdc8d6432fef 100644 +--- a/drivers/tty/serial/8250/8250_dma.c ++++ b/drivers/tty/serial/8250/8250_dma.c +@@ -86,6 +86,8 @@ int serial8250_tx_dma(struct uart_8250_port *p) + + dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); + ++ serial8250_do_prepare_tx_dma(p); ++ + desc = dmaengine_prep_slave_single(dma->txchan, + dma->tx_addr + xmit->tail, + dma->tx_size, DMA_MEM_TO_DEV, +@@ -123,6 +125,8 @@ int serial8250_rx_dma(struct uart_8250_port *p) + if (dma->rx_running) + return 0; + ++ serial8250_do_prepare_rx_dma(p); ++ + desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr, + dma->rx_size, DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); +diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c +index 49559731bbcf1..ace221afeb039 100644 +--- a/drivers/tty/serial/8250/8250_dw.c ++++ b/drivers/tty/serial/8250/8250_dw.c +@@ -124,12 +124,15 @@ static void dw8250_check_lcr(struct uart_port *p, int value) + /* Returns once the transmitter is empty or we run out of retries */ + static void dw8250_tx_wait_empty(struct uart_port *p) + { ++ struct uart_8250_port *up = up_to_u8250p(p); + unsigned int tries = 20000; + unsigned int delay_threshold = tries - 1000; + unsigned int lsr; + + while (tries--) { + lsr = readb (p->membase + (UART_LSR << p->regshift)); ++ up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; ++ + if (lsr & UART_LSR_TEMT) + break; + +diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c +index fc65a2293ce9e..af74f82ad7825 100644 +--- a/drivers/tty/serial/8250/8250_fsl.c ++++ b/drivers/tty/serial/8250/8250_fsl.c +@@ -81,7 +81,7 @@ int fsl8250_handle_irq(struct uart_port *port) + if ((lsr & UART_LSR_THRE) && (up->ier & UART_IER_THRI)) + serial8250_tx_chars(up); + +- up->lsr_saved_flags = orig_lsr; ++ up->lsr_saved_flags |= orig_lsr & UART_LSR_BI; + + uart_unlock_and_check_sysrq_irqrestore(&up->port, flags); + +diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c +index e7b9805903f4c..a16743856fc7e 100644 +--- a/drivers/tty/serial/8250/8250_pci.c ++++ b/drivers/tty/serial/8250/8250_pci.c +@@ -11,6 +11,7 @@ + #include <linux/pci.h> + #include <linux/string.h> + #include <linux/kernel.h> ++#include <linux/math.h> + #include <linux/slab.h> + #include <linux/delay.h> + #include <linux/tty.h> +@@ -75,13 +76,12 @@ static int pci_default_setup(struct serial_private*, + + static void moan_device(const char *str, struct pci_dev *dev) + { +- dev_err(&dev->dev, +- "%s: %s\n" ++ pci_err(dev, "%s\n" + "Please send the output of lspci -vv, this\n" + "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n" + "manufacturer and name of serial board or\n" + "modem board to <linux-serial@vger.kernel.org>.\n", +- pci_name(dev), str, dev->vendor, dev->device, ++ str, dev->vendor, dev->device, + dev->subsystem_vendor, dev->subsystem_device); + } + +@@ -238,7 +238,7 @@ static int pci_inteli960ni_init(struct pci_dev *dev) + /* is firmware started? */ + pci_read_config_dword(dev, 0x44, &oldval); + if (oldval == 0x00001000L) { /* RESET value */ +- dev_dbg(&dev->dev, "Local i960 firmware missing\n"); ++ pci_dbg(dev, "Local i960 firmware missing\n"); + return -ENODEV; + } + return 0; +@@ -588,9 +588,8 @@ static int pci_timedia_probe(struct pci_dev *dev) + * (0,2,3,5,6: serial only -- 7,8,9: serial + parallel) + */ + if ((dev->subsystem_device & 0x00f0) >= 0x70) { +- dev_info(&dev->dev, +- "ignoring Timedia subdevice %04x for parport_serial\n", +- dev->subsystem_device); ++ pci_info(dev, "ignoring Timedia subdevice %04x for parport_serial\n", ++ dev->subsystem_device); + return -ENODEV; + } + +@@ -827,8 +826,7 @@ static int pci_netmos_9900_numports(struct pci_dev *dev) + if (sub_serports > 0) + return sub_serports; + +- dev_err(&dev->dev, +- "NetMos/Mostech serial driver ignoring port on ambiguous config.\n"); ++ pci_err(dev, "NetMos/Mostech serial driver ignoring port on ambiguous config.\n"); + return 0; + } + +@@ -897,18 +895,16 @@ static int pci_netmos_init(struct pci_dev *dev) + /* enable IO_Space bit */ + #define ITE_887x_POSIO_ENABLE (1 << 31) + ++/* inta_addr are the configuration addresses of the ITE */ ++static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0, 0x200, 0x280 }; + static int pci_ite887x_init(struct pci_dev *dev) + { +- /* inta_addr are the configuration addresses of the ITE */ +- static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0, +- 0x200, 0x280, 0 }; + int ret, i, type; + struct resource *iobase = NULL; + u32 miscr, uartbar, ioport; + + /* search for the base-ioport */ +- i = 0; +- while (inta_addr[i] && iobase == NULL) { ++ for (i = 0; i < ARRAY_SIZE(inta_addr); i++) { + iobase = request_region(inta_addr[i], ITE_887x_IOSIZE, + "ite887x"); + if (iobase != NULL) { +@@ -925,13 +921,11 @@ static int pci_ite887x_init(struct pci_dev *dev) + break; + } + release_region(iobase->start, ITE_887x_IOSIZE); +- iobase = NULL; + } +- i++; + } + +- if (!inta_addr[i]) { +- dev_err(&dev->dev, "ite887x: could not find iobase\n"); ++ if (i == ARRAY_SIZE(inta_addr)) { ++ pci_err(dev, "could not find iobase\n"); + return -ENODEV; + } + +@@ -1001,43 +995,29 @@ static void pci_ite887x_exit(struct pci_dev *dev) + } + + /* +- * EndRun Technologies. +- * Determine the number of ports available on the device. ++ * Oxford Semiconductor Inc. ++ * Check if an OxSemi device is part of the Tornado range of devices. + */ + #define PCI_VENDOR_ID_ENDRUN 0x7401 + #define PCI_DEVICE_ID_ENDRUN_1588 0xe100 + +-static int pci_endrun_init(struct pci_dev *dev) ++static bool pci_oxsemi_tornado_p(struct pci_dev *dev) + { +- u8 __iomem *p; +- unsigned long deviceID; +- unsigned int number_uarts = 0; ++ /* OxSemi Tornado devices are all 0xCxxx */ ++ if (dev->vendor == PCI_VENDOR_ID_OXSEMI && ++ (dev->device & 0xf000) != 0xc000) ++ return false; + +- /* EndRun device is all 0xexxx */ ++ /* EndRun devices are all 0xExxx */ + if (dev->vendor == PCI_VENDOR_ID_ENDRUN && +- (dev->device & 0xf000) != 0xe000) +- return 0; +- +- p = pci_iomap(dev, 0, 5); +- if (p == NULL) +- return -ENOMEM; ++ (dev->device & 0xf000) != 0xe000) ++ return false; + +- deviceID = ioread32(p); +- /* EndRun device */ +- if (deviceID == 0x07000200) { +- number_uarts = ioread8(p + 4); +- dev_dbg(&dev->dev, +- "%d ports detected on EndRun PCI Express device\n", +- number_uarts); +- } +- pci_iounmap(dev, p); +- return number_uarts; ++ return true; + } + + /* +- * Oxford Semiconductor Inc. +- * Check that device is part of the Tornado range of devices, then determine +- * the number of ports available on the device. ++ * Determine the number of ports available on a Tornado device. + */ + static int pci_oxsemi_tornado_init(struct pci_dev *dev) + { +@@ -1045,9 +1025,7 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev) + unsigned long deviceID; + unsigned int number_uarts = 0; + +- /* OxSemi Tornado devices are all 0xCxxx */ +- if (dev->vendor == PCI_VENDOR_ID_OXSEMI && +- (dev->device & 0xF000) != 0xC000) ++ if (!pci_oxsemi_tornado_p(dev)) + return 0; + + p = pci_iomap(dev, 0, 5); +@@ -1058,14 +1036,217 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev) + /* Tornado device */ + if (deviceID == 0x07000200) { + number_uarts = ioread8(p + 4); +- dev_dbg(&dev->dev, +- "%d ports detected on Oxford PCI Express device\n", +- number_uarts); ++ pci_dbg(dev, "%d ports detected on %s PCI Express device\n", ++ number_uarts, ++ dev->vendor == PCI_VENDOR_ID_ENDRUN ? ++ "EndRun" : "Oxford"); + } + pci_iounmap(dev, p); + return number_uarts; + } + ++/* Tornado-specific constants for the TCR and CPR registers; see below. */ ++#define OXSEMI_TORNADO_TCR_MASK 0xf ++#define OXSEMI_TORNADO_CPR_MASK 0x1ff ++#define OXSEMI_TORNADO_CPR_MIN 0x008 ++#define OXSEMI_TORNADO_CPR_DEF 0x10f ++ ++/* ++ * Determine the oversampling rate, the clock prescaler, and the clock ++ * divisor for the requested baud rate. The clock rate is 62.5 MHz, ++ * which is four times the baud base, and the prescaler increments in ++ * steps of 1/8. Therefore to make calculations on integers we need ++ * to use a scaled clock rate, which is the baud base multiplied by 32 ++ * (or our assumed UART clock rate multiplied by 2). ++ * ++ * The allowed oversampling rates are from 4 up to 16 inclusive (values ++ * from 0 to 3 inclusive map to 16). Likewise the clock prescaler allows ++ * values between 1.000 and 63.875 inclusive (operation for values from ++ * 0.000 to 0.875 has not been specified). The clock divisor is the usual ++ * unsigned 16-bit integer. ++ * ++ * For the most accurate baud rate we use a table of predetermined ++ * oversampling rates and clock prescalers that records all possible ++ * products of the two parameters in the range from 4 up to 255 inclusive, ++ * and additionally 335 for the 1500000bps rate, with the prescaler scaled ++ * by 8. The table is sorted by the decreasing value of the oversampling ++ * rate and ties are resolved by sorting by the decreasing value of the ++ * product. This way preference is given to higher oversampling rates. ++ * ++ * We iterate over the table and choose the product of an oversampling ++ * rate and a clock prescaler that gives the lowest integer division ++ * result deviation, or if an exact integer divider is found we stop ++ * looking for it right away. We do some fixup if the resulting clock ++ * divisor required would be out of its unsigned 16-bit integer range. ++ * ++ * Finally we abuse the supposed fractional part returned to encode the ++ * 4-bit value of the oversampling rate and the 9-bit value of the clock ++ * prescaler which will end up in the TCR and CPR/CPR2 registers. ++ */ ++static unsigned int pci_oxsemi_tornado_get_divisor(struct uart_port *port, ++ unsigned int baud, ++ unsigned int *frac) ++{ ++ static u8 p[][2] = { ++ { 16, 14, }, { 16, 13, }, { 16, 12, }, { 16, 11, }, ++ { 16, 10, }, { 16, 9, }, { 16, 8, }, { 15, 17, }, ++ { 15, 16, }, { 15, 15, }, { 15, 14, }, { 15, 13, }, ++ { 15, 12, }, { 15, 11, }, { 15, 10, }, { 15, 9, }, ++ { 15, 8, }, { 14, 18, }, { 14, 17, }, { 14, 14, }, ++ { 14, 13, }, { 14, 12, }, { 14, 11, }, { 14, 10, }, ++ { 14, 9, }, { 14, 8, }, { 13, 19, }, { 13, 18, }, ++ { 13, 17, }, { 13, 13, }, { 13, 12, }, { 13, 11, }, ++ { 13, 10, }, { 13, 9, }, { 13, 8, }, { 12, 19, }, ++ { 12, 18, }, { 12, 17, }, { 12, 11, }, { 12, 9, }, ++ { 12, 8, }, { 11, 23, }, { 11, 22, }, { 11, 21, }, ++ { 11, 20, }, { 11, 19, }, { 11, 18, }, { 11, 17, }, ++ { 11, 11, }, { 11, 10, }, { 11, 9, }, { 11, 8, }, ++ { 10, 25, }, { 10, 23, }, { 10, 20, }, { 10, 19, }, ++ { 10, 17, }, { 10, 10, }, { 10, 9, }, { 10, 8, }, ++ { 9, 27, }, { 9, 23, }, { 9, 21, }, { 9, 19, }, ++ { 9, 18, }, { 9, 17, }, { 9, 9, }, { 9, 8, }, ++ { 8, 31, }, { 8, 29, }, { 8, 23, }, { 8, 19, }, ++ { 8, 17, }, { 8, 8, }, { 7, 35, }, { 7, 31, }, ++ { 7, 29, }, { 7, 25, }, { 7, 23, }, { 7, 21, }, ++ { 7, 19, }, { 7, 17, }, { 7, 15, }, { 7, 14, }, ++ { 7, 13, }, { 7, 12, }, { 7, 11, }, { 7, 10, }, ++ { 7, 9, }, { 7, 8, }, { 6, 41, }, { 6, 37, }, ++ { 6, 31, }, { 6, 29, }, { 6, 23, }, { 6, 19, }, ++ { 6, 17, }, { 6, 13, }, { 6, 11, }, { 6, 10, }, ++ { 6, 9, }, { 6, 8, }, { 5, 67, }, { 5, 47, }, ++ { 5, 43, }, { 5, 41, }, { 5, 37, }, { 5, 31, }, ++ { 5, 29, }, { 5, 25, }, { 5, 23, }, { 5, 19, }, ++ { 5, 17, }, { 5, 15, }, { 5, 13, }, { 5, 11, }, ++ { 5, 10, }, { 5, 9, }, { 5, 8, }, { 4, 61, }, ++ { 4, 59, }, { 4, 53, }, { 4, 47, }, { 4, 43, }, ++ { 4, 41, }, { 4, 37, }, { 4, 31, }, { 4, 29, }, ++ { 4, 23, }, { 4, 19, }, { 4, 17, }, { 4, 13, }, ++ { 4, 9, }, { 4, 8, }, ++ }; ++ /* Scale the quotient for comparison to get the fractional part. */ ++ const unsigned int quot_scale = 65536; ++ unsigned int sclk = port->uartclk * 2; ++ unsigned int sdiv = DIV_ROUND_CLOSEST(sclk, baud); ++ unsigned int best_squot; ++ unsigned int squot; ++ unsigned int quot; ++ u16 cpr; ++ u8 tcr; ++ int i; ++ ++ /* Old custom speed handling. */ ++ if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) { ++ unsigned int cust_div = port->custom_divisor; ++ ++ quot = cust_div & UART_DIV_MAX; ++ tcr = (cust_div >> 16) & OXSEMI_TORNADO_TCR_MASK; ++ cpr = (cust_div >> 20) & OXSEMI_TORNADO_CPR_MASK; ++ if (cpr < OXSEMI_TORNADO_CPR_MIN) ++ cpr = OXSEMI_TORNADO_CPR_DEF; ++ } else { ++ best_squot = quot_scale; ++ for (i = 0; i < ARRAY_SIZE(p); i++) { ++ unsigned int spre; ++ unsigned int srem; ++ u8 cp; ++ u8 tc; ++ ++ tc = p[i][0]; ++ cp = p[i][1]; ++ spre = tc * cp; ++ ++ srem = sdiv % spre; ++ if (srem > spre / 2) ++ srem = spre - srem; ++ squot = DIV_ROUND_CLOSEST(srem * quot_scale, spre); ++ ++ if (srem == 0) { ++ tcr = tc; ++ cpr = cp; ++ quot = sdiv / spre; ++ break; ++ } else if (squot < best_squot) { ++ best_squot = squot; ++ tcr = tc; ++ cpr = cp; ++ quot = DIV_ROUND_CLOSEST(sdiv, spre); ++ } ++ } ++ while (tcr <= (OXSEMI_TORNADO_TCR_MASK + 1) >> 1 && ++ quot % 2 == 0) { ++ quot >>= 1; ++ tcr <<= 1; ++ } ++ while (quot > UART_DIV_MAX) { ++ if (tcr <= (OXSEMI_TORNADO_TCR_MASK + 1) >> 1) { ++ quot >>= 1; ++ tcr <<= 1; ++ } else if (cpr <= OXSEMI_TORNADO_CPR_MASK >> 1) { ++ quot >>= 1; ++ cpr <<= 1; ++ } else { ++ quot = quot * cpr / OXSEMI_TORNADO_CPR_MASK; ++ cpr = OXSEMI_TORNADO_CPR_MASK; ++ } ++ } ++ } ++ ++ *frac = (cpr << 8) | (tcr & OXSEMI_TORNADO_TCR_MASK); ++ return quot; ++} ++ ++/* ++ * Set the oversampling rate in the transmitter clock cycle register (TCR), ++ * the clock prescaler in the clock prescaler register (CPR and CPR2), and ++ * the clock divisor in the divisor latch (DLL and DLM). Note that for ++ * backwards compatibility any write to CPR clears CPR2 and therefore CPR ++ * has to be written first, followed by CPR2, which occupies the location ++ * of CKS used with earlier UART designs. ++ */ ++static void pci_oxsemi_tornado_set_divisor(struct uart_port *port, ++ unsigned int baud, ++ unsigned int quot, ++ unsigned int quot_frac) ++{ ++ struct uart_8250_port *up = up_to_u8250p(port); ++ u8 cpr2 = quot_frac >> 16; ++ u8 cpr = quot_frac >> 8; ++ u8 tcr = quot_frac; ++ ++ serial_icr_write(up, UART_TCR, tcr); ++ serial_icr_write(up, UART_CPR, cpr); ++ serial_icr_write(up, UART_CKS, cpr2); ++ serial8250_do_set_divisor(port, baud, quot, 0); ++} ++ ++/* ++ * For Tornado devices we force MCR[7] set for the Divide-by-M N/8 baud rate ++ * generator prescaler (CPR and CPR2). Otherwise no prescaler would be used. ++ */ ++static void pci_oxsemi_tornado_set_mctrl(struct uart_port *port, ++ unsigned int mctrl) ++{ ++ struct uart_8250_port *up = up_to_u8250p(port); ++ ++ up->mcr |= UART_MCR_CLKSEL; ++ serial8250_do_set_mctrl(port, mctrl); ++} ++ ++static int pci_oxsemi_tornado_setup(struct serial_private *priv, ++ const struct pciserial_board *board, ++ struct uart_8250_port *up, int idx) ++{ ++ struct pci_dev *dev = priv->dev; ++ ++ if (pci_oxsemi_tornado_p(dev)) { ++ up->port.get_divisor = pci_oxsemi_tornado_get_divisor; ++ up->port.set_divisor = pci_oxsemi_tornado_set_divisor; ++ up->port.set_mctrl = pci_oxsemi_tornado_set_mctrl; ++ } ++ ++ return pci_default_setup(priv, board, up, idx); ++} ++ + static int pci_asix_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +@@ -1120,15 +1301,15 @@ static struct quatech_feature quatech_cards[] = { + { 0, } + }; + +-static int pci_quatech_amcc(u16 devid) ++static int pci_quatech_amcc(struct pci_dev *dev) + { + struct quatech_feature *qf = &quatech_cards[0]; + while (qf->devid) { +- if (qf->devid == devid) ++ if (qf->devid == dev->device) + return qf->amcc; + qf++; + } +- pr_err("quatech: unknown port type '0x%04X'.\n", devid); ++ pci_err(dev, "unknown port type '0x%04X'.\n", dev->device); + return 0; + }; + +@@ -1291,7 +1472,7 @@ static int pci_quatech_rs422(struct uart_8250_port *port) + + static int pci_quatech_init(struct pci_dev *dev) + { +- if (pci_quatech_amcc(dev->device)) { ++ if (pci_quatech_amcc(dev)) { + unsigned long base = pci_resource_start(dev, 0); + if (base) { + u32 tmp; +@@ -1315,7 +1496,7 @@ static int pci_quatech_setup(struct serial_private *priv, + port->port.uartclk = pci_quatech_clock(port); + /* For now just warn about RS422 */ + if (pci_quatech_rs422(port)) +- pr_warn("quatech: software control of RS422 features not currently supported.\n"); ++ pci_warn(priv->dev, "software control of RS422 features not currently supported.\n"); + return pci_default_setup(priv, board, port, idx); + } + +@@ -1529,7 +1710,7 @@ static int pci_fintek_setup(struct serial_private *priv, + /* Get the io address from configuration space */ + pci_read_config_word(pdev, config_base + 4, &iobase); + +- dev_dbg(&pdev->dev, "%s: idx=%d iobase=0x%x", __func__, idx, iobase); ++ pci_dbg(pdev, "idx=%d iobase=0x%x", idx, iobase); + + port->port.iotype = UPIO_PORT; + port->port.iobase = iobase; +@@ -1693,7 +1874,7 @@ static int skip_tx_en_setup(struct serial_private *priv, + struct uart_8250_port *port, int idx) + { + port->port.quirks |= UPQ_NO_TXEN_TEST; +- dev_dbg(&priv->dev->dev, ++ pci_dbg(priv->dev, + "serial8250: skipping TxEn test for device [%04x:%04x] subsystem [%04x:%04x]\n", + priv->dev->vendor, priv->dev->device, + priv->dev->subsystem_vendor, priv->dev->subsystem_device); +@@ -2517,7 +2698,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = { + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, +- .init = pci_endrun_init, ++ .init = pci_oxsemi_tornado_init, + .setup = pci_default_setup, + }, + /* +@@ -2529,7 +2710,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = { + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_oxsemi_tornado_init, +- .setup = pci_default_setup, ++ .setup = pci_oxsemi_tornado_setup, + }, + { + .vendor = PCI_VENDOR_ID_MAINPINE, +@@ -2537,7 +2718,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = { + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_oxsemi_tornado_init, +- .setup = pci_default_setup, ++ .setup = pci_oxsemi_tornado_setup, + }, + { + .vendor = PCI_VENDOR_ID_DIGI, +@@ -2545,7 +2726,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = { + .subvendor = PCI_SUBVENDOR_ID_IBM, + .subdevice = PCI_ANY_ID, + .init = pci_oxsemi_tornado_init, +- .setup = pci_default_setup, ++ .setup = pci_oxsemi_tornado_setup, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, +@@ -2862,7 +3043,7 @@ enum pci_board_num_t { + pbn_b0_2_1843200, + pbn_b0_4_1843200, + +- pbn_b0_1_3906250, ++ pbn_b0_1_15625000, + + pbn_b0_bt_1_115200, + pbn_b0_bt_2_115200, +@@ -2940,12 +3121,11 @@ enum pci_board_num_t { + pbn_panacom2, + pbn_panacom4, + pbn_plx_romulus, +- pbn_endrun_2_3906250, + pbn_oxsemi, +- pbn_oxsemi_1_3906250, +- pbn_oxsemi_2_3906250, +- pbn_oxsemi_4_3906250, +- pbn_oxsemi_8_3906250, ++ pbn_oxsemi_1_15625000, ++ pbn_oxsemi_2_15625000, ++ pbn_oxsemi_4_15625000, ++ pbn_oxsemi_8_15625000, + pbn_intel_i960, + pbn_sgi_ioc3, + pbn_computone_4, +@@ -3092,10 +3272,10 @@ static struct pciserial_board pci_boards[] = { + .uart_offset = 8, + }, + +- [pbn_b0_1_3906250] = { ++ [pbn_b0_1_15625000] = { + .flags = FL_BASE0, + .num_ports = 1, +- .base_baud = 3906250, ++ .base_baud = 15625000, + .uart_offset = 8, + }, + +@@ -3466,20 +3646,6 @@ static struct pciserial_board pci_boards[] = { + .first_offset = 0x03, + }, + +- /* +- * EndRun Technologies +- * Uses the size of PCI Base region 0 to +- * signal now many ports are available +- * 2 port 952 Uart support +- */ +- [pbn_endrun_2_3906250] = { +- .flags = FL_BASE0, +- .num_ports = 2, +- .base_baud = 3906250, +- .uart_offset = 0x200, +- .first_offset = 0x1000, +- }, +- + /* + * This board uses the size of PCI Base region 0 to + * signal now many ports are available +@@ -3490,31 +3656,31 @@ static struct pciserial_board pci_boards[] = { + .base_baud = 115200, + .uart_offset = 8, + }, +- [pbn_oxsemi_1_3906250] = { ++ [pbn_oxsemi_1_15625000] = { + .flags = FL_BASE0, + .num_ports = 1, +- .base_baud = 3906250, ++ .base_baud = 15625000, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, +- [pbn_oxsemi_2_3906250] = { ++ [pbn_oxsemi_2_15625000] = { + .flags = FL_BASE0, + .num_ports = 2, +- .base_baud = 3906250, ++ .base_baud = 15625000, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, +- [pbn_oxsemi_4_3906250] = { ++ [pbn_oxsemi_4_15625000] = { + .flags = FL_BASE0, + .num_ports = 4, +- .base_baud = 3906250, ++ .base_baud = 15625000, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, +- [pbn_oxsemi_8_3906250] = { ++ [pbn_oxsemi_8_15625000] = { + .flags = FL_BASE0, + .num_ports = 8, +- .base_baud = 3906250, ++ .base_baud = 15625000, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, +@@ -4011,12 +4177,12 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board) + uart.port.irq = 0; + } else { + if (pci_match_id(pci_use_msi, dev)) { +- dev_dbg(&dev->dev, "Using MSI(-X) interrupts\n"); ++ pci_dbg(dev, "Using MSI(-X) interrupts\n"); + pci_set_master(dev); + uart.port.flags &= ~UPF_SHARE_IRQ; + rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_ALL_TYPES); + } else { +- dev_dbg(&dev->dev, "Using legacy interrupts\n"); ++ pci_dbg(dev, "Using legacy interrupts\n"); + rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_LEGACY); + } + if (rc < 0) { +@@ -4034,12 +4200,12 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board) + if (quirk->setup(priv, board, &uart, i)) + break; + +- dev_dbg(&dev->dev, "Setup PCI port: port %lx, irq %d, type %d\n", ++ pci_dbg(dev, "Setup PCI port: port %lx, irq %d, type %d\n", + uart.port.iobase, uart.port.irq, uart.port.iotype); + + priv->line[i] = serial8250_register_8250_port(&uart); + if (priv->line[i] < 0) { +- dev_err(&dev->dev, ++ pci_err(dev, + "Couldn't register serial port %lx, irq %d, type %d, error %d\n", + uart.port.iobase, uart.port.irq, + uart.port.iotype, priv->line[i]); +@@ -4135,8 +4301,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) + } + + if (ent->driver_data >= ARRAY_SIZE(pci_boards)) { +- dev_err(&dev->dev, "invalid driver_data: %ld\n", +- ent->driver_data); ++ pci_err(dev, "invalid driver_data: %ld\n", ent->driver_data); + return -EINVAL; + } + +@@ -4219,7 +4384,7 @@ static int pciserial_resume_one(struct device *dev) + err = pci_enable_device(pdev); + /* FIXME: We cannot simply error out here */ + if (err) +- dev_err(dev, "Unable to re-enable ports, trying to continue.\n"); ++ pci_err(pdev, "Unable to re-enable ports, trying to continue.\n"); + pciserial_resume_ports(priv); + } + return 0; +@@ -4412,13 +4577,6 @@ static const struct pci_device_id serial_pci_tbl[] = { + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS, + 0x10b5, 0x106a, 0, 0, + pbn_plx_romulus }, +- /* +- * EndRun Technologies. PCI express device range. +- * EndRun PTP/1588 has 2 Native UARTs. +- */ +- { PCI_VENDOR_ID_ENDRUN, PCI_DEVICE_ID_ENDRUN_1588, +- PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_endrun_2_3906250 }, + /* + * Quatech cards. These actually have configurable clocks but for + * now we just use the default. +@@ -4528,158 +4686,165 @@ static const struct pci_device_id serial_pci_tbl[] = { + */ + { PCI_VENDOR_ID_OXSEMI, 0xc101, /* OXPCIe952 1 Legacy UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_b0_1_3906250 }, ++ pbn_b0_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc105, /* OXPCIe952 1 Legacy UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_b0_1_3906250 }, ++ pbn_b0_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc11b, /* OXPCIe952 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc11f, /* OXPCIe952 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc120, /* OXPCIe952 1 Legacy UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_b0_1_3906250 }, ++ pbn_b0_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc124, /* OXPCIe952 1 Legacy UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_b0_1_3906250 }, ++ pbn_b0_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc138, /* OXPCIe952 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc13d, /* OXPCIe952 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc140, /* OXPCIe952 1 Legacy UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_b0_1_3906250 }, ++ pbn_b0_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc141, /* OXPCIe952 1 Legacy UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_b0_1_3906250 }, ++ pbn_b0_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc144, /* OXPCIe952 1 Legacy UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_b0_1_3906250 }, ++ pbn_b0_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc145, /* OXPCIe952 1 Legacy UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_b0_1_3906250 }, ++ pbn_b0_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc158, /* OXPCIe952 2 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_2_3906250 }, ++ pbn_oxsemi_2_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc15d, /* OXPCIe952 2 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_2_3906250 }, ++ pbn_oxsemi_2_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc208, /* OXPCIe954 4 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_4_3906250 }, ++ pbn_oxsemi_4_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc20d, /* OXPCIe954 4 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_4_3906250 }, ++ pbn_oxsemi_4_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc308, /* OXPCIe958 8 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_8_3906250 }, ++ pbn_oxsemi_8_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc30d, /* OXPCIe958 8 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_8_3906250 }, ++ pbn_oxsemi_8_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc40b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc40f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc41b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc41f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc42b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc42f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc43b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc43f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc44b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc44f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc45b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc45f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc46b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc46f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc47b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc47f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc48b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc48f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc49b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc49f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc4ab, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc4af, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc4bb, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc4bf, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc4cb, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc4cf, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + /* + * Mainpine Inc. IQ Express "Rev3" utilizing OxSemi Tornado + */ + { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 1 Port V.34 Super-G3 Fax */ + PCI_VENDOR_ID_MAINPINE, 0x4001, 0, 0, +- pbn_oxsemi_1_3906250 }, ++ pbn_oxsemi_1_15625000 }, + { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 2 Port V.34 Super-G3 Fax */ + PCI_VENDOR_ID_MAINPINE, 0x4002, 0, 0, +- pbn_oxsemi_2_3906250 }, ++ pbn_oxsemi_2_15625000 }, + { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 4 Port V.34 Super-G3 Fax */ + PCI_VENDOR_ID_MAINPINE, 0x4004, 0, 0, +- pbn_oxsemi_4_3906250 }, ++ pbn_oxsemi_4_15625000 }, + { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */ + PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0, +- pbn_oxsemi_8_3906250 }, ++ pbn_oxsemi_8_15625000 }, + + /* + * Digi/IBM PCIe 2-port Async EIA-232 Adapter utilizing OxSemi Tornado + */ + { PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM, + PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0, +- pbn_oxsemi_2_3906250 }, ++ pbn_oxsemi_2_15625000 }, ++ /* ++ * EndRun Technologies. PCI express device range. ++ * EndRun PTP/1588 has 2 Native UARTs utilizing OxSemi 952. ++ */ ++ { PCI_VENDOR_ID_ENDRUN, PCI_DEVICE_ID_ENDRUN_1588, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_oxsemi_2_15625000 }, + + /* + * SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards, +@@ -5310,6 +5475,115 @@ static const struct pci_device_id serial_pci_tbl[] = { + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_b2_4_115200 }, ++ /* ++ * Brainboxes PX-101 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x4005, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b0_2_115200 }, ++ { PCI_VENDOR_ID_INTASHIELD, 0x4019, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_oxsemi_2_15625000 }, ++ /* ++ * Brainboxes PX-235/246 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x4004, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b0_1_115200 }, ++ { PCI_VENDOR_ID_INTASHIELD, 0x4016, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_oxsemi_1_15625000 }, ++ /* ++ * Brainboxes PX-203/PX-257 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x4006, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b0_2_115200 }, ++ { PCI_VENDOR_ID_INTASHIELD, 0x4015, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_oxsemi_4_15625000 }, ++ /* ++ * Brainboxes PX-260/PX-701 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x400A, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_oxsemi_4_15625000 }, ++ /* ++ * Brainboxes PX-310 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x400E, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_oxsemi_2_15625000 }, ++ /* ++ * Brainboxes PX-313 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x400C, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_oxsemi_2_15625000 }, ++ /* ++ * Brainboxes PX-320/324/PX-376/PX-387 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x400B, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_oxsemi_1_15625000 }, ++ /* ++ * Brainboxes PX-335/346 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x400F, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_oxsemi_4_15625000 }, ++ /* ++ * Brainboxes PX-368 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x4010, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_oxsemi_4_15625000 }, ++ /* ++ * Brainboxes PX-420 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x4000, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b0_4_115200 }, ++ { PCI_VENDOR_ID_INTASHIELD, 0x4011, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_oxsemi_4_15625000 }, ++ /* ++ * Brainboxes PX-803 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x4009, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b0_1_115200 }, ++ { PCI_VENDOR_ID_INTASHIELD, 0x401E, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_oxsemi_1_15625000 }, ++ /* ++ * Brainboxes PX-846 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x4008, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b0_1_115200 }, ++ { PCI_VENDOR_ID_INTASHIELD, 0x4017, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_oxsemi_1_15625000 }, ++ + /* + * Perle PCI-RAS cards + */ +diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c +index 4f66825abe675..a5496bd1b6503 100644 +--- a/drivers/tty/serial/8250/8250_port.c ++++ b/drivers/tty/serial/8250/8250_port.c +@@ -537,27 +537,6 @@ serial_port_out_sync(struct uart_port *p, int offset, int value) + } + } + +-/* +- * For the 16C950 +- */ +-static void serial_icr_write(struct uart_8250_port *up, int offset, int value) +-{ +- serial_out(up, UART_SCR, offset); +- serial_out(up, UART_ICR, value); +-} +- +-static unsigned int serial_icr_read(struct uart_8250_port *up, int offset) +-{ +- unsigned int value; +- +- serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD); +- serial_out(up, UART_SCR, offset); +- value = serial_in(up, UART_ICR); +- serial_icr_write(up, UART_ACR, up->acr); +- +- return value; +-} +- + /* + * FIFO support. + */ +diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c +index 481107fdd69bc..4155bd10711da 100644 +--- a/drivers/tty/serial/fsl_lpuart.c ++++ b/drivers/tty/serial/fsl_lpuart.c +@@ -982,12 +982,12 @@ static void lpuart32_rxint(struct lpuart_port *sport) + + if (sr & (UARTSTAT_PE | UARTSTAT_OR | UARTSTAT_FE)) { + if (sr & UARTSTAT_PE) { ++ sport->port.icount.parity++; ++ } else if (sr & UARTSTAT_FE) { + if (is_break) + sport->port.icount.brk++; + else +- sport->port.icount.parity++; +- } else if (sr & UARTSTAT_FE) { +- sport->port.icount.frame++; ++ sport->port.icount.frame++; + } + + if (sr & UARTSTAT_OR) +@@ -1002,12 +1002,12 @@ static void lpuart32_rxint(struct lpuart_port *sport) + sr &= sport->port.read_status_mask; + + if (sr & UARTSTAT_PE) { ++ flg = TTY_PARITY; ++ } else if (sr & UARTSTAT_FE) { + if (is_break) + flg = TTY_BREAK; + else +- flg = TTY_PARITY; +- } else if (sr & UARTSTAT_FE) { +- flg = TTY_FRAME; ++ flg = TTY_FRAME; + } + + if (sr & UARTSTAT_OR) +diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c +index 8eb64898b159d..1074a0fdf7a1c 100644 +--- a/drivers/tty/serial/mvebu-uart.c ++++ b/drivers/tty/serial/mvebu-uart.c +@@ -237,6 +237,7 @@ static void mvebu_uart_rx_chars(struct uart_port *port, unsigned int status) + struct tty_port *tport = &port->state->port; + unsigned char ch = 0; + char flag = 0; ++ int ret; + + do { + if (status & STAT_RX_RDY(port)) { +@@ -249,6 +250,16 @@ static void mvebu_uart_rx_chars(struct uart_port *port, unsigned int status) + port->icount.parity++; + } + ++ /* ++ * For UART2, error bits are not cleared on buffer read. ++ * This causes interrupt loop and system hang. ++ */ ++ if (IS_EXTENDED(port) && (status & STAT_BRK_ERR)) { ++ ret = readl(port->membase + UART_STAT); ++ ret |= STAT_BRK_ERR; ++ writel(ret, port->membase + UART_STAT); ++ } ++ + if (status & STAT_BRK_DET) { + port->icount.brk++; + status &= ~(STAT_FRM_ERR | STAT_PAR_ERR); +diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c +index dfc1f4b445f3b..6eaf8eb846619 100644 +--- a/drivers/tty/vt/vt.c ++++ b/drivers/tty/vt/vt.c +@@ -344,7 +344,7 @@ static struct uni_screen *vc_uniscr_alloc(unsigned int cols, unsigned int rows) + /* allocate everything in one go */ + memsize = cols * rows * sizeof(char32_t); + memsize += rows * sizeof(char32_t *); +- p = vmalloc(memsize); ++ p = vzalloc(memsize); + if (!p) + return NULL; + +diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c +index d6d515d598dc0..ae049eb28b93c 100644 +--- a/drivers/usb/cdns3/cdns3-gadget.c ++++ b/drivers/usb/cdns3/cdns3-gadget.c +@@ -2280,11 +2280,16 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep, + int ret = 0; + int val; + ++ if (!ep) { ++ pr_debug("usbss: ep not configured?\n"); ++ return -EINVAL; ++ } ++ + priv_ep = ep_to_cdns3_ep(ep); + priv_dev = priv_ep->cdns3_dev; + comp_desc = priv_ep->endpoint.comp_desc; + +- if (!ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT) { ++ if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT) { + dev_dbg(priv_dev->dev, "usbss: invalid parameters\n"); + return -EINVAL; + } +@@ -2596,7 +2601,7 @@ int cdns3_gadget_ep_dequeue(struct usb_ep *ep, + struct usb_request *request) + { + struct cdns3_endpoint *priv_ep = ep_to_cdns3_ep(ep); +- struct cdns3_device *priv_dev = priv_ep->cdns3_dev; ++ struct cdns3_device *priv_dev; + struct usb_request *req, *req_temp; + struct cdns3_request *priv_req; + struct cdns3_trb *link_trb; +@@ -2607,6 +2612,8 @@ int cdns3_gadget_ep_dequeue(struct usb_ep *ep, + if (!ep || !request || !ep->desc) + return -EINVAL; + ++ priv_dev = priv_ep->cdns3_dev; ++ + spin_lock_irqsave(&priv_dev->lock, flags); + + priv_req = to_cdns3_request(request); +diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c +index 9e28d715fa3b7..6c5934dbe9b3f 100644 +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -1691,7 +1691,6 @@ static void usb_giveback_urb_bh(struct tasklet_struct *t) + + spin_lock_irq(&bh->lock); + bh->running = true; +- restart: + list_replace_init(&bh->head, &local_list); + spin_unlock_irq(&bh->lock); + +@@ -1705,10 +1704,17 @@ static void usb_giveback_urb_bh(struct tasklet_struct *t) + bh->completing_ep = NULL; + } + +- /* check if there are new URBs to giveback */ ++ /* ++ * giveback new URBs next time to prevent this function ++ * from not exiting for a long time. ++ */ + spin_lock_irq(&bh->lock); +- if (!list_empty(&bh->head)) +- goto restart; ++ if (!list_empty(&bh->head)) { ++ if (bh->high_prio) ++ tasklet_hi_schedule(&bh->bh); ++ else ++ tasklet_schedule(&bh->bh); ++ } + bh->running = false; + spin_unlock_irq(&bh->lock); + } +@@ -1737,7 +1743,7 @@ static void usb_giveback_urb_bh(struct tasklet_struct *t) + void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status) + { + struct giveback_urb_bh *bh; +- bool running, high_prio_bh; ++ bool running; + + /* pass status to tasklet via unlinked */ + if (likely(!urb->unlinked)) +@@ -1748,13 +1754,10 @@ void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status) + return; + } + +- if (usb_pipeisoc(urb->pipe) || usb_pipeint(urb->pipe)) { ++ if (usb_pipeisoc(urb->pipe) || usb_pipeint(urb->pipe)) + bh = &hcd->high_prio_bh; +- high_prio_bh = true; +- } else { ++ else + bh = &hcd->low_prio_bh; +- high_prio_bh = false; +- } + + spin_lock(&bh->lock); + list_add_tail(&urb->urb_list, &bh->head); +@@ -1763,7 +1766,7 @@ void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status) + + if (running) + ; +- else if (high_prio_bh) ++ else if (bh->high_prio) + tasklet_hi_schedule(&bh->bh); + else + tasklet_schedule(&bh->bh); +@@ -2959,6 +2962,7 @@ int usb_add_hcd(struct usb_hcd *hcd, + + /* initialize tasklets */ + init_giveback_urb_bh(&hcd->high_prio_bh); ++ hcd->high_prio_bh.high_prio = true; + init_giveback_urb_bh(&hcd->low_prio_bh); + + /* enable irqs just before we start the controller, +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index 5cb1350ec66d1..cfac5503aa662 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -158,8 +158,13 @@ static void __dwc3_set_mode(struct work_struct *work) + break; + } + +- /* For DRD host or device mode only */ +- if (dwc->desired_dr_role != DWC3_GCTL_PRTCAP_OTG) { ++ /* ++ * When current_dr_role is not set, there's no role switching. ++ * Only perform GCTL.CoreSoftReset when there's DRD role switching. ++ */ ++ if (dwc->current_dr_role && ((DWC3_IP_IS(DWC3) || ++ DWC3_VER_IS_PRIOR(DWC31, 190A)) && ++ dwc->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); +diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c +index b81a9e1c13153..873bf5041117f 100644 +--- a/drivers/usb/dwc3/dwc3-qcom.c ++++ b/drivers/usb/dwc3/dwc3-qcom.c +@@ -443,9 +443,9 @@ static int dwc3_qcom_get_irq(struct platform_device *pdev, + int ret; + + if (np) +- ret = platform_get_irq_byname(pdev_irq, name); ++ ret = platform_get_irq_byname_optional(pdev_irq, name); + else +- ret = platform_get_irq(pdev_irq, num); ++ ret = platform_get_irq_optional(pdev_irq, num); + + return ret; + } +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index e534b98205ca6..322754a7f91ca 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -1169,17 +1169,49 @@ static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep) + return trbs_left; + } + +-static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, +- dma_addr_t dma, unsigned int length, unsigned int chain, +- unsigned int node, unsigned int stream_id, +- unsigned int short_not_ok, unsigned int no_interrupt, +- unsigned int is_last, bool must_interrupt) ++/** ++ * dwc3_prepare_one_trb - setup one TRB from one request ++ * @dep: endpoint for which this request is prepared ++ * @req: dwc3_request pointer ++ * @trb_length: buffer size of the TRB ++ * @chain: should this TRB be chained to the next? ++ * @node: only for isochronous endpoints. First TRB needs different type. ++ * @use_bounce_buffer: set to use bounce buffer ++ * @must_interrupt: set to interrupt on TRB completion ++ */ ++static void dwc3_prepare_one_trb(struct dwc3_ep *dep, ++ struct dwc3_request *req, unsigned int trb_length, ++ unsigned int chain, unsigned int node, bool use_bounce_buffer, ++ bool must_interrupt) + { ++ struct dwc3_trb *trb; ++ dma_addr_t dma; ++ unsigned int stream_id = req->request.stream_id; ++ unsigned int short_not_ok = req->request.short_not_ok; ++ unsigned int no_interrupt = req->request.no_interrupt; ++ unsigned int is_last = req->request.is_last; + struct dwc3 *dwc = dep->dwc; + struct usb_gadget *gadget = dwc->gadget; + enum usb_device_speed speed = gadget->speed; + +- trb->size = DWC3_TRB_SIZE_LENGTH(length); ++ if (use_bounce_buffer) ++ dma = dep->dwc->bounce_addr; ++ else if (req->request.num_sgs > 0) ++ dma = sg_dma_address(req->start_sg); ++ else ++ dma = req->request.dma; ++ ++ trb = &dep->trb_pool[dep->trb_enqueue]; ++ ++ if (!req->trb) { ++ dwc3_gadget_move_started_request(req); ++ req->trb = trb; ++ req->trb_dma = dwc3_trb_dma_offset(dep, trb); ++ } ++ ++ req->num_trbs++; ++ ++ trb->size = DWC3_TRB_SIZE_LENGTH(trb_length); + trb->bpl = lower_32_bits(dma); + trb->bph = upper_32_bits(dma); + +@@ -1219,10 +1251,10 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, + unsigned int mult = 2; + unsigned int maxp = usb_endpoint_maxp(ep->desc); + +- if (length <= (2 * maxp)) ++ if (req->request.length <= (2 * maxp)) + mult--; + +- if (length <= maxp) ++ if (req->request.length <= maxp) + mult--; + + trb->size |= DWC3_TRB_SIZE_PCM1(mult); +@@ -1291,50 +1323,6 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, + trace_dwc3_prepare_trb(dep, trb); + } + +-/** +- * dwc3_prepare_one_trb - setup one TRB from one request +- * @dep: endpoint for which this request is prepared +- * @req: dwc3_request pointer +- * @trb_length: buffer size of the TRB +- * @chain: should this TRB be chained to the next? +- * @node: only for isochronous endpoints. First TRB needs different type. +- * @use_bounce_buffer: set to use bounce buffer +- * @must_interrupt: set to interrupt on TRB completion +- */ +-static void dwc3_prepare_one_trb(struct dwc3_ep *dep, +- struct dwc3_request *req, unsigned int trb_length, +- unsigned int chain, unsigned int node, bool use_bounce_buffer, +- bool must_interrupt) +-{ +- struct dwc3_trb *trb; +- dma_addr_t dma; +- unsigned int stream_id = req->request.stream_id; +- unsigned int short_not_ok = req->request.short_not_ok; +- unsigned int no_interrupt = req->request.no_interrupt; +- unsigned int is_last = req->request.is_last; +- +- if (use_bounce_buffer) +- dma = dep->dwc->bounce_addr; +- else if (req->request.num_sgs > 0) +- dma = sg_dma_address(req->start_sg); +- else +- dma = req->request.dma; +- +- trb = &dep->trb_pool[dep->trb_enqueue]; +- +- if (!req->trb) { +- dwc3_gadget_move_started_request(req); +- req->trb = trb; +- req->trb_dma = dwc3_trb_dma_offset(dep, trb); +- } +- +- req->num_trbs++; +- +- __dwc3_prepare_one_trb(dep, trb, dma, trb_length, chain, node, +- stream_id, short_not_ok, no_interrupt, is_last, +- must_interrupt); +-} +- + static bool dwc3_needs_extra_trb(struct dwc3_ep *dep, struct dwc3_request *req) + { + unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); +diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig +index 69394dc1cdfb6..2cdd37be165a4 100644 +--- a/drivers/usb/gadget/udc/Kconfig ++++ b/drivers/usb/gadget/udc/Kconfig +@@ -311,7 +311,7 @@ source "drivers/usb/gadget/udc/bdc/Kconfig" + + config USB_AMD5536UDC + tristate "AMD5536 UDC" +- depends on USB_PCI ++ depends on USB_PCI && HAS_DMA + select USB_SNP_CORE + help + The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge. +diff --git a/drivers/usb/gadget/udc/aspeed-vhub/hub.c b/drivers/usb/gadget/udc/aspeed-vhub/hub.c +index b9960fdd8a515..16a12d2d492e2 100644 +--- a/drivers/usb/gadget/udc/aspeed-vhub/hub.c ++++ b/drivers/usb/gadget/udc/aspeed-vhub/hub.c +@@ -1028,8 +1028,10 @@ static int ast_vhub_init_desc(struct ast_vhub *vhub) + /* Initialize vhub String Descriptors. */ + INIT_LIST_HEAD(&vhub->vhub_str_desc); + desc_np = of_get_child_by_name(vhub_np, "vhub-strings"); +- if (desc_np) ++ if (desc_np) { + ret = ast_vhub_of_parse_str_desc(vhub, desc_np); ++ of_node_put(desc_np); ++ } + else + ret = ast_vhub_str_alloc_add(vhub, &ast_vhub_strings); + +diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c +index be76f891b9c52..cb4ddfa52cb0f 100644 +--- a/drivers/usb/gadget/udc/tegra-xudc.c ++++ b/drivers/usb/gadget/udc/tegra-xudc.c +@@ -3689,15 +3689,15 @@ static int tegra_xudc_powerdomain_init(struct tegra_xudc *xudc) + int err; + + xudc->genpd_dev_device = dev_pm_domain_attach_by_name(dev, "dev"); +- if (IS_ERR(xudc->genpd_dev_device)) { +- err = PTR_ERR(xudc->genpd_dev_device); ++ if (IS_ERR_OR_NULL(xudc->genpd_dev_device)) { ++ err = PTR_ERR(xudc->genpd_dev_device) ? : -ENODATA; + dev_err(dev, "failed to get device power domain: %d\n", err); + return err; + } + + xudc->genpd_dev_ss = dev_pm_domain_attach_by_name(dev, "ss"); +- if (IS_ERR(xudc->genpd_dev_ss)) { +- err = PTR_ERR(xudc->genpd_dev_ss); ++ if (IS_ERR_OR_NULL(xudc->genpd_dev_ss)) { ++ err = PTR_ERR(xudc->genpd_dev_ss) ? : -ENODATA; + dev_err(dev, "failed to get SuperSpeed power domain: %d\n", err); + return err; + } +diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c +index 6bbaee74f7e7d..28a19693c19fe 100644 +--- a/drivers/usb/host/ehci-ppc-of.c ++++ b/drivers/usb/host/ehci-ppc-of.c +@@ -148,6 +148,7 @@ static int ehci_hcd_ppc_of_probe(struct platform_device *op) + } else { + ehci->has_amcc_usb23 = 1; + } ++ of_node_put(np); + } + + if (of_get_property(dn, "big-endian", NULL)) { +diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c +index 85878e8ad3311..106a6bcefb087 100644 +--- a/drivers/usb/host/ohci-nxp.c ++++ b/drivers/usb/host/ohci-nxp.c +@@ -164,6 +164,7 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev) + } + + isp1301_i2c_client = isp1301_get_client(isp1301_node); ++ of_node_put(isp1301_node); + if (!isp1301_i2c_client) + return -EPROBE_DEFER; + +diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c +index 996958a6565c3..bdb776553826b 100644 +--- a/drivers/usb/host/xhci-tegra.c ++++ b/drivers/usb/host/xhci-tegra.c +@@ -1010,15 +1010,15 @@ static int tegra_xusb_powerdomain_init(struct device *dev, + int err; + + tegra->genpd_dev_host = dev_pm_domain_attach_by_name(dev, "xusb_host"); +- if (IS_ERR(tegra->genpd_dev_host)) { +- err = PTR_ERR(tegra->genpd_dev_host); ++ if (IS_ERR_OR_NULL(tegra->genpd_dev_host)) { ++ err = PTR_ERR(tegra->genpd_dev_host) ? : -ENODATA; + dev_err(dev, "failed to get host pm-domain: %d\n", err); + return err; + } + + tegra->genpd_dev_ss = dev_pm_domain_attach_by_name(dev, "xusb_ss"); +- if (IS_ERR(tegra->genpd_dev_ss)) { +- err = PTR_ERR(tegra->genpd_dev_ss); ++ if (IS_ERR_OR_NULL(tegra->genpd_dev_ss)) { ++ err = PTR_ERR(tegra->genpd_dev_ss) ? : -ENODATA; + dev_err(dev, "failed to get superspeed pm-domain: %d\n", err); + return err; + } +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 79fa34f1e31c4..101f1956a96ca 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -2395,7 +2395,7 @@ static inline const char *xhci_decode_trb(char *str, size_t size, + field3 & TRB_CYCLE ? 'C' : 'c'); + break; + case TRB_STOP_RING: +- sprintf(str, ++ snprintf(str, size, + "%s: slot %d sp %d ep %d flags %c", + xhci_trb_type_string(type), + TRB_TO_SLOT_ID(field3), +diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c +index 9d56138133a97..ef6a2891f290c 100644 +--- a/drivers/usb/serial/sierra.c ++++ b/drivers/usb/serial/sierra.c +@@ -737,7 +737,8 @@ static void sierra_close(struct usb_serial_port *port) + + /* + * Need to take susp_lock to make sure port is not already being +- * resumed, but no need to hold it due to initialized ++ * resumed, but no need to hold it due to the tty-port initialized ++ * flag. + */ + spin_lock_irq(&intfdata->susp_lock); + if (--intfdata->open_ports == 0) +diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c +index 090a78c948f28..255fb9583c0a2 100644 +--- a/drivers/usb/serial/usb-serial.c ++++ b/drivers/usb/serial/usb-serial.c +@@ -292,7 +292,7 @@ static int serial_open(struct tty_struct *tty, struct file *filp) + * + * Shut down a USB serial port. Serialized against activate by the + * tport mutex and kept to matching open/close pairs +- * of calls by the initialized flag. ++ * of calls by the tty-port initialized flag. + * + * Not called if tty is console. + */ +diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c +index cb01283d4d159..f21f25a8cf6fe 100644 +--- a/drivers/usb/serial/usb_wwan.c ++++ b/drivers/usb/serial/usb_wwan.c +@@ -389,7 +389,8 @@ void usb_wwan_close(struct usb_serial_port *port) + + /* + * Need to take susp_lock to make sure port is not already being +- * resumed, but no need to hold it due to initialized ++ * resumed, but no need to hold it due to the tty-port initialized ++ * flag. + */ + spin_lock_irq(&intfdata->susp_lock); + if (--intfdata->open_ports == 0) +diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c +index 8a7e2dd52ad5a..1f23eb543d8fe 100644 +--- a/drivers/usb/typec/ucsi/ucsi.c ++++ b/drivers/usb/typec/ucsi/ucsi.c +@@ -76,6 +76,10 @@ static int ucsi_read_error(struct ucsi *ucsi) + if (ret) + return ret; + ++ ret = ucsi_acknowledge_command(ucsi); ++ if (ret) ++ return ret; ++ + switch (error) { + case UCSI_ERROR_INCOMPATIBLE_PARTNER: + return -EOPNOTSUPP; +diff --git a/drivers/video/fbdev/amba-clcd.c b/drivers/video/fbdev/amba-clcd.c +index 8080116aea844..f65c96d1394d3 100644 +--- a/drivers/video/fbdev/amba-clcd.c ++++ b/drivers/video/fbdev/amba-clcd.c +@@ -698,16 +698,18 @@ static int clcdfb_of_init_display(struct clcd_fb *fb) + return -ENODEV; + + panel = of_graph_get_remote_port_parent(endpoint); +- if (!panel) +- return -ENODEV; ++ if (!panel) { ++ err = -ENODEV; ++ goto out_endpoint_put; ++ } + + err = clcdfb_of_get_backlight(&fb->dev->dev, fb->panel); + if (err) +- return err; ++ goto out_panel_put; + + err = clcdfb_of_get_mode(&fb->dev->dev, panel, fb->panel); + if (err) +- return err; ++ goto out_panel_put; + + err = of_property_read_u32(fb->dev->dev.of_node, "max-memory-bandwidth", + &max_bandwidth); +@@ -736,11 +738,21 @@ static int clcdfb_of_init_display(struct clcd_fb *fb) + + if (of_property_read_u32_array(endpoint, + "arm,pl11x,tft-r0g0b0-pads", +- tft_r0b0g0, ARRAY_SIZE(tft_r0b0g0)) != 0) +- return -ENOENT; ++ tft_r0b0g0, ARRAY_SIZE(tft_r0b0g0)) != 0) { ++ err = -ENOENT; ++ goto out_panel_put; ++ } ++ ++ of_node_put(panel); ++ of_node_put(endpoint); + + return clcdfb_of_init_tft_panel(fb, tft_r0b0g0[0], + tft_r0b0g0[1], tft_r0b0g0[2]); ++out_panel_put: ++ of_node_put(panel); ++out_endpoint_put: ++ of_node_put(endpoint); ++ return err; + } + + static int clcdfb_of_vram_setup(struct clcd_fb *fb) +diff --git a/drivers/video/fbdev/arkfb.c b/drivers/video/fbdev/arkfb.c +index edf169d0816e6..8d092b1064706 100644 +--- a/drivers/video/fbdev/arkfb.c ++++ b/drivers/video/fbdev/arkfb.c +@@ -778,7 +778,12 @@ static int arkfb_set_par(struct fb_info *info) + return -EINVAL; + } + +- ark_set_pixclock(info, (hdiv * info->var.pixclock) / hmul); ++ value = (hdiv * info->var.pixclock) / hmul; ++ if (!value) { ++ fb_dbg(info, "invalid pixclock\n"); ++ value = 1; ++ } ++ ark_set_pixclock(info, value); + svga_set_timings(par->state.vgabase, &ark_timing_regs, &(info->var), hmul, hdiv, + (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, + (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1, +@@ -789,6 +794,8 @@ static int arkfb_set_par(struct fb_info *info) + value = ((value * hmul / hdiv) / 8) - 5; + vga_wcrt(par->state.vgabase, 0x42, (value + 1) / 2); + ++ if (screen_size > info->screen_size) ++ screen_size = info->screen_size; + memset_io(info->screen_base, 0x00, screen_size); + /* Device and screen back on */ + svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80); +diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c +index bb83e7c53ae0e..fb02105d6337b 100644 +--- a/drivers/video/fbdev/core/fbcon.c ++++ b/drivers/video/fbdev/core/fbcon.c +@@ -115,8 +115,8 @@ static int logo_lines; + enums. */ + static int logo_shown = FBCON_LOGO_CANSHOW; + /* console mappings */ +-static int first_fb_vc; +-static int last_fb_vc = MAX_NR_CONSOLES - 1; ++static unsigned int first_fb_vc; ++static unsigned int last_fb_vc = MAX_NR_CONSOLES - 1; + static int fbcon_is_default = 1; + static int primary_device = -1; + static int fbcon_has_console_bind; +@@ -464,10 +464,12 @@ static int __init fb_console_setup(char *this_opt) + options += 3; + if (*options) + first_fb_vc = simple_strtoul(options, &options, 10) - 1; +- if (first_fb_vc < 0) ++ if (first_fb_vc >= MAX_NR_CONSOLES) + first_fb_vc = 0; + if (*options++ == '-') + last_fb_vc = simple_strtoul(options, &options, 10) - 1; ++ if (last_fb_vc < first_fb_vc || last_fb_vc >= MAX_NR_CONSOLES) ++ last_fb_vc = MAX_NR_CONSOLES - 1; + fbcon_is_default = 0; + continue; + } +@@ -1704,8 +1706,6 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, + case SM_UP: + if (count > vc->vc_rows) /* Maximum realistic size */ + count = vc->vc_rows; +- if (logo_shown >= 0) +- goto redraw_up; + switch (fb_scrollmode(p)) { + case SCROLL_MOVE: + fbcon_redraw_blit(vc, info, p, t, b - t - count, +@@ -1794,8 +1794,6 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, + case SM_DOWN: + if (count > vc->vc_rows) /* Maximum realistic size */ + count = vc->vc_rows; +- if (logo_shown >= 0) +- goto redraw_down; + switch (fb_scrollmode(p)) { + case SCROLL_MOVE: + fbcon_redraw_blit(vc, info, p, b - 1, b - t - count, +diff --git a/drivers/video/fbdev/s3fb.c b/drivers/video/fbdev/s3fb.c +index 5c74253e7b2c0..a936455a3df2a 100644 +--- a/drivers/video/fbdev/s3fb.c ++++ b/drivers/video/fbdev/s3fb.c +@@ -902,6 +902,8 @@ static int s3fb_set_par(struct fb_info *info) + value = clamp((htotal + hsstart + 1) / 2 + 2, hsstart + 4, htotal + 1); + svga_wcrt_multi(par->state.vgabase, s3_dtpc_regs, value); + ++ if (screen_size > info->screen_size) ++ screen_size = info->screen_size; + memset_io(info->screen_base, 0x00, screen_size); + /* Device and screen back on */ + svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80); +diff --git a/drivers/video/fbdev/sis/init.c b/drivers/video/fbdev/sis/init.c +index b568c646a76c2..2ba91d62af92e 100644 +--- a/drivers/video/fbdev/sis/init.c ++++ b/drivers/video/fbdev/sis/init.c +@@ -355,12 +355,12 @@ SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, + } + break; + case 400: +- if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 800) && (LCDwidth >= 600))) { ++ if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 800) && (LCDheight >= 600))) { + if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth]; + } + break; + case 512: +- if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 1024) && (LCDwidth >= 768))) { ++ if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 1024) && (LCDheight >= 768))) { + if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth]; + } + break; +diff --git a/drivers/video/fbdev/vt8623fb.c b/drivers/video/fbdev/vt8623fb.c +index 7a959e5ba90b8..c274ec5e965ca 100644 +--- a/drivers/video/fbdev/vt8623fb.c ++++ b/drivers/video/fbdev/vt8623fb.c +@@ -504,6 +504,8 @@ static int vt8623fb_set_par(struct fb_info *info) + (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, 1, + 1, info->node); + ++ if (screen_size > info->screen_size) ++ screen_size = info->screen_size; + memset_io(info->screen_base, 0x00, screen_size); + + /* Device and screen back on */ +diff --git a/drivers/watchdog/armada_37xx_wdt.c b/drivers/watchdog/armada_37xx_wdt.c +index 1635f421ef2c3..854b1cc723cb6 100644 +--- a/drivers/watchdog/armada_37xx_wdt.c ++++ b/drivers/watchdog/armada_37xx_wdt.c +@@ -274,6 +274,8 @@ static int armada_37xx_wdt_probe(struct platform_device *pdev) + if (!res) + return -ENODEV; + dev->reg = devm_ioremap(&pdev->dev, res->start, resource_size(res)); ++ if (!dev->reg) ++ return -ENOMEM; + + /* init clock */ + dev->clk = devm_clk_get(&pdev->dev, NULL); +diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c +index 4820af929a826..4afc468d8ed12 100644 +--- a/drivers/watchdog/sp5100_tco.c ++++ b/drivers/watchdog/sp5100_tco.c +@@ -394,6 +394,7 @@ out: + iounmap(addr); + + release_resource(res); ++ kfree(res); + + return ret; + } +diff --git a/fs/9p/acl.c b/fs/9p/acl.c +index c381499f54160..da22415ed036c 100644 +--- a/fs/9p/acl.c ++++ b/fs/9p/acl.c +@@ -123,6 +123,7 @@ static int v9fs_set_acl(struct p9_fid *fid, int type, struct posix_acl *acl) + char *name; + size_t size; + void *buffer; ++ + if (!acl) + return 0; + +diff --git a/fs/9p/acl.h b/fs/9p/acl.h +index d43c8949e807b..bc87b36f529e8 100644 +--- a/fs/9p/acl.h ++++ b/fs/9p/acl.h +@@ -15,14 +15,15 @@ + #define FS_9P_ACL_H + + #ifdef CONFIG_9P_FS_POSIX_ACL +-extern int v9fs_get_acl(struct inode *, struct p9_fid *); +-extern struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type, bool rcu); +-extern int v9fs_acl_chmod(struct inode *, struct p9_fid *); +-extern int v9fs_set_create_acl(struct inode *, struct p9_fid *, +- struct posix_acl *, struct posix_acl *); +-extern int v9fs_acl_mode(struct inode *dir, umode_t *modep, +- struct posix_acl **dpacl, struct posix_acl **pacl); +-extern void v9fs_put_acl(struct posix_acl *dacl, struct posix_acl *acl); ++int v9fs_get_acl(struct inode *inode, struct p9_fid *fid); ++struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type, ++ bool rcu); ++int v9fs_acl_chmod(struct inode *inode, struct p9_fid *fid); ++int v9fs_set_create_acl(struct inode *inode, struct p9_fid *fid, ++ struct posix_acl *dacl, struct posix_acl *acl); ++int v9fs_acl_mode(struct inode *dir, umode_t *modep, ++ struct posix_acl **dpacl, struct posix_acl **pacl); ++void v9fs_put_acl(struct posix_acl *dacl, struct posix_acl *acl); + #else + #define v9fs_iop_get_acl NULL + static inline int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) +diff --git a/fs/9p/cache.c b/fs/9p/cache.c +index 1769a44f48192..41da71320482c 100644 +--- a/fs/9p/cache.c ++++ b/fs/9p/cache.c +@@ -19,8 +19,8 @@ + #define CACHETAG_LEN 11 + + struct fscache_netfs v9fs_cache_netfs = { +- .name = "9p", +- .version = 0, ++ .name = "9p", ++ .version = 0, + }; + + /* +diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c +index 2e0fa7c932db0..141067379f5e4 100644 +--- a/fs/9p/v9fs.c ++++ b/fs/9p/v9fs.c +@@ -190,8 +190,10 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) + + while ((p = strsep(&options, ",")) != NULL) { + int token, r; ++ + if (!*p) + continue; ++ + token = match_token(p, tokens, args); + switch (token) { + case Opt_debug: +@@ -659,6 +661,7 @@ static void v9fs_destroy_inode_cache(void) + static int v9fs_cache_register(void) + { + int ret; ++ + ret = v9fs_init_inode_cache(); + if (ret < 0) + return ret; +@@ -686,6 +689,7 @@ static void v9fs_cache_unregister(void) + static int __init init_v9fs(void) + { + int err; ++ + pr_info("Installing v9fs 9p2000 file system support\n"); + /* TODO: Setup list of registered trasnport modules */ + +diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h +index d44ade76966a0..bc417da7e9c1d 100644 +--- a/fs/9p/v9fs_vfs.h ++++ b/fs/9p/v9fs_vfs.h +@@ -44,9 +44,10 @@ extern struct kmem_cache *v9fs_inode_cache; + + struct inode *v9fs_alloc_inode(struct super_block *sb); + void v9fs_free_inode(struct inode *inode); +-struct inode *v9fs_get_inode(struct super_block *sb, umode_t mode, dev_t); ++struct inode *v9fs_get_inode(struct super_block *sb, umode_t mode, ++ dev_t rdev); + int v9fs_init_inode(struct v9fs_session_info *v9ses, +- struct inode *inode, umode_t mode, dev_t); ++ struct inode *inode, umode_t mode, dev_t rdev); + void v9fs_evict_inode(struct inode *inode); + ino_t v9fs_qid2ino(struct p9_qid *qid); + void v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, +@@ -59,8 +60,8 @@ void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat); + int v9fs_uflags2omode(int uflags, int extended); + + void v9fs_blank_wstat(struct p9_wstat *wstat); +-int v9fs_vfs_setattr_dotl(struct user_namespace *, struct dentry *, +- struct iattr *); ++int v9fs_vfs_setattr_dotl(struct user_namespace *mnt_userns, ++ struct dentry *dentry, struct iattr *iattr); + int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end, + int datasync); + int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode); +@@ -68,9 +69,9 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode); + static inline void v9fs_invalidate_inode_attr(struct inode *inode) + { + struct v9fs_inode *v9inode; ++ + v9inode = V9FS_I(inode); + v9inode->cache_validity |= V9FS_INO_INVALID_ATTR; +- return; + } + + int v9fs_open_to_dotl_flags(int flags); +diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c +index 1c4f1b39cc950..606d33ef35c66 100644 +--- a/fs/9p/vfs_addr.c ++++ b/fs/9p/vfs_addr.c +@@ -242,11 +242,13 @@ v9fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) + loff_t pos = iocb->ki_pos; + ssize_t n; + int err = 0; ++ + if (iov_iter_rw(iter) == WRITE) { + n = p9_client_write(file->private_data, pos, iter, &err); + if (n) { + struct inode *inode = file_inode(file); + loff_t i_size = i_size_read(inode); ++ + if (pos + n > i_size) + inode_add_bytes(inode, pos + n - i_size); + } +@@ -257,7 +259,7 @@ v9fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) + } + + static int v9fs_write_begin(struct file *filp, struct address_space *mapping, +- loff_t pos, unsigned len, unsigned flags, ++ loff_t pos, unsigned int len, unsigned int flags, + struct page **pagep, void **fsdata) + { + int retval = 0; +@@ -293,7 +295,7 @@ out: + } + + static int v9fs_write_end(struct file *filp, struct address_space *mapping, +- loff_t pos, unsigned len, unsigned copied, ++ loff_t pos, unsigned int len, unsigned int copied, + struct page *page, void *fsdata) + { + loff_t last_pos = pos + copied; +diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c +index 4b4292123b3d1..c2736af97884f 100644 +--- a/fs/9p/vfs_dentry.c ++++ b/fs/9p/vfs_dentry.c +@@ -52,6 +52,7 @@ static int v9fs_cached_dentry_delete(const struct dentry *dentry) + static void v9fs_dentry_release(struct dentry *dentry) + { + struct hlist_node *p, *n; ++ + p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p)\n", + dentry, dentry); + hlist_for_each_safe(p, n, (struct hlist_head *)&dentry->d_fsdata) +@@ -76,6 +77,7 @@ static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags) + if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) { + int retval; + struct v9fs_session_info *v9ses; ++ + fid = v9fs_fid_lookup(dentry); + if (IS_ERR(fid)) + return PTR_ERR(fid); +diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c +index 246235ebdb70a..7437b185fa8eb 100644 +--- a/fs/9p/vfs_file.c ++++ b/fs/9p/vfs_file.c +@@ -408,6 +408,7 @@ v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) + struct inode *inode = file_inode(file); + loff_t i_size; + unsigned long pg_start, pg_end; ++ + pg_start = origin >> PAGE_SHIFT; + pg_end = (origin + retval - 1) >> PAGE_SHIFT; + if (inode->i_mapping && inode->i_mapping->nrpages) +diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c +index 15d9492536cf5..0d9b7d453a877 100644 +--- a/fs/9p/vfs_inode.c ++++ b/fs/9p/vfs_inode.c +@@ -49,6 +49,7 @@ static const struct inode_operations v9fs_symlink_inode_operations; + static u32 unixmode2p9mode(struct v9fs_session_info *v9ses, umode_t mode) + { + int res; ++ + res = mode & 0777; + if (S_ISDIR(mode)) + res |= P9_DMDIR; +@@ -223,6 +224,7 @@ v9fs_blank_wstat(struct p9_wstat *wstat) + struct inode *v9fs_alloc_inode(struct super_block *sb) + { + struct v9fs_inode *v9inode; ++ + v9inode = kmem_cache_alloc(v9fs_inode_cache, GFP_KERNEL); + if (!v9inode) + return NULL; +@@ -251,7 +253,7 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses, + { + int err = 0; + +- inode_init_owner(&init_user_ns,inode, NULL, mode); ++ inode_init_owner(&init_user_ns, inode, NULL, mode); + inode->i_blocks = 0; + inode->i_rdev = rdev; + inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); +@@ -440,7 +442,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb, + unsigned long i_ino; + struct inode *inode; + struct v9fs_session_info *v9ses = sb->s_fs_info; +- int (*test)(struct inode *, void *); ++ int (*test)(struct inode *inode, void *data); + + if (new) + test = v9fs_test_new_inode; +@@ -499,8 +501,10 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, + static int v9fs_at_to_dotl_flags(int flags) + { + int rflags = 0; ++ + if (flags & AT_REMOVEDIR) + rflags |= P9_DOTL_AT_REMOVEDIR; ++ + return rflags; + } + +@@ -797,7 +801,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, + + static int + v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, +- struct file *file, unsigned flags, umode_t mode) ++ struct file *file, unsigned int flags, umode_t mode) + { + int err; + u32 perm; +@@ -1084,7 +1088,7 @@ static int v9fs_vfs_setattr(struct user_namespace *mnt_userns, + fid = v9fs_fid_lookup(dentry); + use_dentry = 1; + } +- if(IS_ERR(fid)) ++ if (IS_ERR(fid)) + return PTR_ERR(fid); + + v9fs_blank_wstat(&wstat); +@@ -1364,7 +1368,7 @@ v9fs_vfs_mknod(struct user_namespace *mnt_userns, struct inode *dir, + char name[2 + U32_MAX_DIGITS + 1 + U32_MAX_DIGITS + 1]; + u32 perm; + +- p9_debug(P9_DEBUG_VFS, " %lu,%pd mode: %hx MAJOR: %u MINOR: %u\n", ++ p9_debug(P9_DEBUG_VFS, " %lu,%pd mode: %x MAJOR: %u MINOR: %u\n", + dir->i_ino, dentry, mode, + MAJOR(rdev), MINOR(rdev)); + +diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c +index 833c638437a72..0f73aa26ddf4b 100644 +--- a/fs/9p/vfs_inode_dotl.c ++++ b/fs/9p/vfs_inode_dotl.c +@@ -107,7 +107,7 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb, + unsigned long i_ino; + struct inode *inode; + struct v9fs_session_info *v9ses = sb->s_fs_info; +- int (*test)(struct inode *, void *); ++ int (*test)(struct inode *inode, void *data); + + if (new) + test = v9fs_test_new_inode_dotl; +@@ -230,7 +230,7 @@ v9fs_vfs_create_dotl(struct user_namespace *mnt_userns, struct inode *dir, + + static int + v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, +- struct file *file, unsigned flags, umode_t omode) ++ struct file *file, unsigned int flags, umode_t omode) + { + int err = 0; + kgid_t gid; +@@ -261,7 +261,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, + v9ses = v9fs_inode2v9ses(dir); + + name = dentry->d_name.name; +- p9_debug(P9_DEBUG_VFS, "name:%s flags:0x%x mode:0x%hx\n", ++ p9_debug(P9_DEBUG_VFS, "name:%s flags:0x%x mode:0x%x\n", + name, flags, omode); + + dfid = v9fs_parent_fid(dentry); +@@ -821,6 +821,7 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir, + if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { + /* Get the latest stat info from server. */ + struct p9_fid *fid; ++ + fid = v9fs_fid_lookup(old_dentry); + if (IS_ERR(fid)) + return PTR_ERR(fid); +@@ -857,7 +858,7 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir, + struct p9_qid qid; + struct posix_acl *dacl = NULL, *pacl = NULL; + +- p9_debug(P9_DEBUG_VFS, " %lu,%pd mode: %hx MAJOR: %u MINOR: %u\n", ++ p9_debug(P9_DEBUG_VFS, " %lu,%pd mode: %x MAJOR: %u MINOR: %u\n", + dir->i_ino, dentry, omode, + MAJOR(rdev), MINOR(rdev)); + +diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c +index 5fce6e30bc5ae..7449f7fd47d22 100644 +--- a/fs/9p/vfs_super.c ++++ b/fs/9p/vfs_super.c +@@ -113,7 +113,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, + struct inode *inode = NULL; + struct dentry *root = NULL; + struct v9fs_session_info *v9ses = NULL; +- umode_t mode = S_IRWXUGO | S_ISVTX; ++ umode_t mode = 0777 | S_ISVTX; + struct p9_fid *fid; + int retval = 0; + +@@ -157,6 +157,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, + sb->s_root = root; + if (v9fs_proto_dotl(v9ses)) { + struct p9_stat_dotl *st = NULL; ++ + st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); + if (IS_ERR(st)) { + retval = PTR_ERR(st); +@@ -167,6 +168,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, + kfree(st); + } else { + struct p9_wstat *st = NULL; ++ + st = p9_client_stat(fid); + if (IS_ERR(st)) { + retval = PTR_ERR(st); +@@ -275,12 +277,13 @@ done: + static int v9fs_drop_inode(struct inode *inode) + { + struct v9fs_session_info *v9ses; ++ + v9ses = v9fs_inode2v9ses(inode); + if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) + return generic_drop_inode(inode); + /* + * in case of non cached mode always drop the +- * the inode because we want the inode attribute ++ * inode because we want the inode attribute + * to always match that on the server. + */ + return 1; +diff --git a/fs/9p/xattr.h b/fs/9p/xattr.h +index c63c3bea5de55..9b28842c63633 100644 +--- a/fs/9p/xattr.h ++++ b/fs/9p/xattr.h +@@ -22,13 +22,14 @@ extern const struct xattr_handler *v9fs_xattr_handlers[]; + extern const struct xattr_handler v9fs_xattr_acl_access_handler; + extern const struct xattr_handler v9fs_xattr_acl_default_handler; + +-extern ssize_t v9fs_fid_xattr_get(struct p9_fid *, const char *, +- void *, size_t); +-extern ssize_t v9fs_xattr_get(struct dentry *, const char *, +- void *, size_t); +-extern int v9fs_fid_xattr_set(struct p9_fid *, const char *, +- const void *, size_t, int); +-extern int v9fs_xattr_set(struct dentry *, const char *, +- const void *, size_t, int); +-extern ssize_t v9fs_listxattr(struct dentry *, char *, size_t); ++ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name, ++ void *buffer, size_t buffer_size); ++ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name, ++ void *buffer, size_t buffer_size); ++int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, ++ const void *value, size_t value_len, int flags); ++int v9fs_xattr_set(struct dentry *dentry, const char *name, ++ const void *value, size_t value_len, int flags); ++ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, ++ size_t buffer_size); + #endif /* FS_9P_XATTR_H */ +diff --git a/fs/attr.c b/fs/attr.c +index dbe996b0dedfc..f581c4d008971 100644 +--- a/fs/attr.c ++++ b/fs/attr.c +@@ -184,6 +184,8 @@ EXPORT_SYMBOL(setattr_prepare); + */ + int inode_newsize_ok(const struct inode *inode, loff_t offset) + { ++ if (offset < 0) ++ return -EINVAL; + if (inode->i_size < offset) { + unsigned long limit; + +diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c +index c6c5a22ff6e86..4b2282aa274e4 100644 +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -3632,6 +3632,7 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, + * attempt. + */ + wait_for_alloc = true; ++ force = CHUNK_ALLOC_NO_FORCE; + spin_unlock(&space_info->lock); + mutex_lock(&fs_info->chunk_mutex); + mutex_unlock(&fs_info->chunk_mutex); +diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c +index 909d19656316f..e65c3039caf1c 100644 +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -3337,16 +3337,6 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device + */ + fs_info->compress_type = BTRFS_COMPRESS_ZLIB; + +- /* +- * Flag our filesystem as having big metadata blocks if they are bigger +- * than the page size. +- */ +- if (btrfs_super_nodesize(disk_super) > PAGE_SIZE) { +- if (!(features & BTRFS_FEATURE_INCOMPAT_BIG_METADATA)) +- btrfs_info(fs_info, +- "flagging fs with big metadata feature"); +- features |= BTRFS_FEATURE_INCOMPAT_BIG_METADATA; +- } + + /* Set up fs_info before parsing mount options */ + nodesize = btrfs_super_nodesize(disk_super); +@@ -3387,6 +3377,17 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device + if (features & BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA) + btrfs_info(fs_info, "has skinny extents"); + ++ /* ++ * Flag our filesystem as having big metadata blocks if they are bigger ++ * than the page size. ++ */ ++ if (btrfs_super_nodesize(disk_super) > PAGE_SIZE) { ++ if (!(features & BTRFS_FEATURE_INCOMPAT_BIG_METADATA)) ++ btrfs_info(fs_info, ++ "flagging fs with big metadata feature"); ++ features |= BTRFS_FEATURE_INCOMPAT_BIG_METADATA; ++ } ++ + /* + * mixed block groups end up with duplicate but slightly offset + * extent buffers for the same range. It leads to corruptions +@@ -3557,6 +3558,20 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device + btrfs_err(fs_info, "failed to init dev_replace: %d", ret); + goto fail_block_groups; + } ++ /* ++ * We have unsupported RO compat features, although RO mounted, we ++ * should not cause any metadata write, including log replay. ++ * Or we could screw up whatever the new feature requires. ++ */ ++ if (unlikely(features && btrfs_super_log_root(disk_super) && ++ !btrfs_test_opt(fs_info, NOLOGREPLAY))) { ++ btrfs_err(fs_info, ++"cannot replay dirty log with unsupported compat_ro features (0x%llx), try rescue=nologreplay", ++ features); ++ err = -EINVAL; ++ goto fail_alloc; ++ } ++ + + ret = btrfs_check_zoned_mode(fs_info); + if (ret) { +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 1b4fee8a2f28b..20d0dea1d0c41 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -1053,6 +1053,28 @@ static u64 get_extent_allocation_hint(struct btrfs_inode *inode, u64 start, + * *page_started is set to one if we unlock locked_page and do everything + * required to start IO on it. It may be clean and already done with + * IO when we return. ++ * ++ * When unlock == 1, we unlock the pages in successfully allocated regions. ++ * When unlock == 0, we leave them locked for writing them out. ++ * ++ * However, we unlock all the pages except @locked_page in case of failure. ++ * ++ * In summary, page locking state will be as follow: ++ * ++ * - page_started == 1 (return value) ++ * - All the pages are unlocked. IO is started. ++ * - Note that this can happen only on success ++ * - unlock == 1 ++ * - All the pages except @locked_page are unlocked in any case ++ * - unlock == 0 ++ * - On success, all the pages are locked for writing out them ++ * - On failure, all the pages except @locked_page are unlocked ++ * ++ * When a failure happens in the second or later iteration of the ++ * while-loop, the ordered extents created in previous iterations are kept ++ * intact. So, the caller must clean them up by calling ++ * btrfs_cleanup_ordered_extents(). See btrfs_run_delalloc_range() for ++ * example. + */ + static noinline int cow_file_range(struct btrfs_inode *inode, + struct page *locked_page, +@@ -1062,6 +1084,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode, + struct btrfs_root *root = inode->root; + struct btrfs_fs_info *fs_info = root->fs_info; + u64 alloc_hint = 0; ++ u64 orig_start = start; + u64 num_bytes; + unsigned long ram_size; + u64 cur_alloc_size = 0; +@@ -1245,18 +1268,44 @@ out_reserve: + btrfs_dec_block_group_reservations(fs_info, ins.objectid); + btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, 1); + out_unlock: ++ /* ++ * Now, we have three regions to clean up: ++ * ++ * |-------(1)----|---(2)---|-------------(3)----------| ++ * `- orig_start `- start `- start + cur_alloc_size `- end ++ * ++ * We process each region below. ++ */ ++ + clear_bits = EXTENT_LOCKED | EXTENT_DELALLOC | EXTENT_DELALLOC_NEW | + EXTENT_DEFRAG | EXTENT_CLEAR_META_RESV; + page_ops = PAGE_UNLOCK | PAGE_START_WRITEBACK | PAGE_END_WRITEBACK; ++ + /* +- * If we reserved an extent for our delalloc range (or a subrange) and +- * failed to create the respective ordered extent, then it means that +- * when we reserved the extent we decremented the extent's size from +- * the data space_info's bytes_may_use counter and incremented the +- * space_info's bytes_reserved counter by the same amount. We must make +- * sure extent_clear_unlock_delalloc() does not try to decrement again +- * the data space_info's bytes_may_use counter, therefore we do not pass +- * it the flag EXTENT_CLEAR_DATA_RESV. ++ * For the range (1). We have already instantiated the ordered extents ++ * for this region. They are cleaned up by ++ * btrfs_cleanup_ordered_extents() in e.g, ++ * btrfs_run_delalloc_range(). EXTENT_LOCKED | EXTENT_DELALLOC are ++ * already cleared in the above loop. And, EXTENT_DELALLOC_NEW | ++ * EXTENT_DEFRAG | EXTENT_CLEAR_META_RESV are handled by the cleanup ++ * function. ++ * ++ * However, in case of unlock == 0, we still need to unlock the pages ++ * (except @locked_page) to ensure all the pages are unlocked. ++ */ ++ if (!unlock && orig_start < start) ++ extent_clear_unlock_delalloc(inode, orig_start, start - 1, ++ locked_page, 0, page_ops); ++ ++ /* ++ * For the range (2). If we reserved an extent for our delalloc range ++ * (or a subrange) and failed to create the respective ordered extent, ++ * then it means that when we reserved the extent we decremented the ++ * extent's size from the data space_info's bytes_may_use counter and ++ * incremented the space_info's bytes_reserved counter by the same ++ * amount. We must make sure extent_clear_unlock_delalloc() does not try ++ * to decrement again the data space_info's bytes_may_use counter, ++ * therefore we do not pass it the flag EXTENT_CLEAR_DATA_RESV. + */ + if (extent_reserved) { + extent_clear_unlock_delalloc(inode, start, +@@ -1268,6 +1317,13 @@ out_unlock: + if (start >= end) + goto out; + } ++ ++ /* ++ * For the range (3). We never touched the region. In addition to the ++ * clear_bits above, we add EXTENT_CLEAR_DATA_RESV to release the data ++ * space_info's bytes_may_use counter, reserved in ++ * btrfs_check_data_free_space(). ++ */ + extent_clear_unlock_delalloc(inode, start, end, locked_page, + clear_bits | EXTENT_CLEAR_DATA_RESV, + page_ops); +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index b23f6b489bb9d..3015a8b20bd99 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -4855,8 +4855,6 @@ void cifs_oplock_break(struct work_struct *work) + struct TCP_Server_Info *server = tcon->ses->server; + int rc = 0; + bool purge_cache = false; +- bool is_deferred = false; +- struct cifs_deferred_close *dclose; + + wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS, + TASK_UNINTERRUPTIBLE); +@@ -4892,22 +4890,6 @@ void cifs_oplock_break(struct work_struct *work) + cifs_dbg(VFS, "Push locks rc = %d\n", rc); + + oplock_break_ack: +- /* +- * When oplock break is received and there are no active +- * file handles but cached, then schedule deferred close immediately. +- * So, new open will not use cached handle. +- */ +- spin_lock(&CIFS_I(inode)->deferred_lock); +- is_deferred = cifs_is_deferred_close(cfile, &dclose); +- spin_unlock(&CIFS_I(inode)->deferred_lock); +- if (is_deferred && +- cfile->deferred_close_scheduled && +- delayed_work_pending(&cfile->deferred)) { +- if (cancel_delayed_work(&cfile->deferred)) { +- _cifsFileInfo_put(cfile, false, false); +- goto oplock_break_done; +- } +- } + /* + * releasing stale oplock after recent reconnect of smb session using + * a now incorrect file handle is not a data integrity issue but do +@@ -4919,7 +4901,7 @@ oplock_break_ack: + cinode); + cifs_dbg(FYI, "Oplock release rc = %d\n", rc); + } +-oplock_break_done: ++ + _cifsFileInfo_put(cfile, false /* do not wait for ourself */, false); + cifs_done_oplock_break(cinode); + } +diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c +index ad3f31380e6b2..8193c14bb1115 100644 +--- a/fs/erofs/decompressor.c ++++ b/fs/erofs/decompressor.c +@@ -93,14 +93,18 @@ static int z_erofs_lz4_prepare_destpages(struct z_erofs_decompress_req *rq, + + if (page) { + __clear_bit(j, bounced); +- if (kaddr) { +- if (kaddr + PAGE_SIZE == page_address(page)) ++ if (!PageHighMem(page)) { ++ if (!i) { ++ kaddr = page_address(page); ++ continue; ++ } ++ if (kaddr && ++ kaddr + PAGE_SIZE == page_address(page)) { + kaddr += PAGE_SIZE; +- else +- kaddr = NULL; +- } else if (!i) { +- kaddr = page_address(page); ++ continue; ++ } + } ++ kaddr = NULL; + continue; + } + kaddr = NULL; +diff --git a/fs/eventpoll.c b/fs/eventpoll.c +index 06f4c5ae1451e..cf326c53db0f7 100644 +--- a/fs/eventpoll.c ++++ b/fs/eventpoll.c +@@ -1740,6 +1740,21 @@ static struct timespec64 *ep_timeout_to_timespec(struct timespec64 *to, long ms) + return to; + } + ++/* ++ * autoremove_wake_function, but remove even on failure to wake up, because we ++ * know that default_wake_function/ttwu will only fail if the thread is already ++ * woken, and in that case the ep_poll loop will remove the entry anyways, not ++ * try to reuse it. ++ */ ++static int ep_autoremove_wake_function(struct wait_queue_entry *wq_entry, ++ unsigned int mode, int sync, void *key) ++{ ++ int ret = default_wake_function(wq_entry, mode, sync, key); ++ ++ list_del_init(&wq_entry->entry); ++ return ret; ++} ++ + /** + * ep_poll - Retrieves ready events, and delivers them to the caller-supplied + * event buffer. +@@ -1821,8 +1836,15 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, + * normal wakeup path no need to call __remove_wait_queue() + * explicitly, thus ep->lock is not taken, which halts the + * event delivery. ++ * ++ * In fact, we now use an even more aggressive function that ++ * unconditionally removes, because we don't reuse the wait ++ * entry between loop iterations. This lets us also avoid the ++ * performance issue if a process is killed, causing all of its ++ * threads to wake up without being removed normally. + */ + init_wait(&wait); ++ wait.func = ep_autoremove_wake_function; + + write_lock_irq(&ep->lock); + /* +diff --git a/fs/exec.c b/fs/exec.c +index 76196ddefbdd0..7d424337b4ec9 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1298,6 +1298,9 @@ int begin_new_exec(struct linux_binprm * bprm) + bprm->mm = NULL; + + #ifdef CONFIG_POSIX_TIMERS ++ spin_lock_irq(&me->sighand->siglock); ++ posix_cpu_timers_exit(me); ++ spin_unlock_irq(&me->sighand->siglock); + exit_itimers(me); + flush_itimer_signals(); + #endif +diff --git a/fs/ext2/super.c b/fs/ext2/super.c +index 3d21279fe2cb5..fd855574ef092 100644 +--- a/fs/ext2/super.c ++++ b/fs/ext2/super.c +@@ -1058,9 +1058,10 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) + sbi->s_frags_per_group); + goto failed_mount; + } +- if (sbi->s_inodes_per_group > sb->s_blocksize * 8) { ++ if (sbi->s_inodes_per_group < sbi->s_inodes_per_block || ++ sbi->s_inodes_per_group > sb->s_blocksize * 8) { + ext2_msg(sb, KERN_ERR, +- "error: #inodes per group too big: %lu", ++ "error: invalid #inodes per group: %lu", + sbi->s_inodes_per_group); + goto failed_mount; + } +@@ -1070,6 +1071,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) + sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) - + le32_to_cpu(es->s_first_data_block) - 1) + / EXT2_BLOCKS_PER_GROUP(sb)) + 1; ++ if ((u64)sbi->s_groups_count * sbi->s_inodes_per_group != ++ le32_to_cpu(es->s_inodes_count)) { ++ ext2_msg(sb, KERN_ERR, "error: invalid #inodes: %u vs computed %llu", ++ le32_to_cpu(es->s_inodes_count), ++ (u64)sbi->s_groups_count * sbi->s_inodes_per_group); ++ goto failed_mount; ++ } + db_count = (sbi->s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) / + EXT2_DESC_PER_BLOCK(sb); + sbi->s_group_desc = kmalloc_array(db_count, +diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c +index 28bc431cf5ba8..38ad09e802e48 100644 +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -35,6 +35,9 @@ static int get_max_inline_xattr_value_size(struct inode *inode, + struct ext4_inode *raw_inode; + int free, min_offs; + ++ if (!EXT4_INODE_HAS_XATTR_SPACE(inode)) ++ return 0; ++ + min_offs = EXT4_SB(inode->i_sb)->s_inode_size - + EXT4_GOOD_OLD_INODE_SIZE - + EXT4_I(inode)->i_extra_isize - +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index f0350d60ba507..98f381f6fc180 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -179,6 +179,8 @@ void ext4_evict_inode(struct inode *inode) + + trace_ext4_evict_inode(inode); + ++ if (EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL) ++ ext4_evict_ea_inode(inode); + if (inode->i_nlink) { + /* + * When journalling data dirty buffers are tracked only in the +@@ -1560,7 +1562,14 @@ static void mpage_release_unused_pages(struct mpage_da_data *mpd, + ext4_lblk_t start, last; + start = index << (PAGE_SHIFT - inode->i_blkbits); + last = end << (PAGE_SHIFT - inode->i_blkbits); ++ ++ /* ++ * avoid racing with extent status tree scans made by ++ * ext4_insert_delayed_block() ++ */ ++ down_write(&EXT4_I(inode)->i_data_sem); + ext4_es_remove_extent(inode, start, last - start + 1); ++ up_write(&EXT4_I(inode)->i_data_sem); + } + + pagevec_init(&pvec); +@@ -3130,13 +3139,15 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block) + { + struct inode *inode = mapping->host; + journal_t *journal; ++ sector_t ret = 0; + int err; + ++ inode_lock_shared(inode); + /* + * We can get here for an inline file via the FIBMAP ioctl + */ + if (ext4_has_inline_data(inode)) +- return 0; ++ goto out; + + if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY) && + test_opt(inode->i_sb, DELALLOC)) { +@@ -3175,10 +3186,14 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block) + jbd2_journal_unlock_updates(journal); + + if (err) +- return 0; ++ goto out; + } + +- return iomap_bmap(mapping, block, &ext4_iomap_ops); ++ ret = iomap_bmap(mapping, block, &ext4_iomap_ops); ++ ++out: ++ inode_unlock_shared(inode); ++ return ret; + } + + static int ext4_readpage(struct file *file, struct page *page) +@@ -4509,8 +4524,7 @@ static inline int ext4_iget_extra_inode(struct inode *inode, + __le32 *magic = (void *)raw_inode + + EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize; + +- if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize + sizeof(__le32) <= +- EXT4_INODE_SIZE(inode->i_sb) && ++ if (EXT4_INODE_HAS_XATTR_SPACE(inode) && + *magic == cpu_to_le32(EXT4_XATTR_MAGIC)) { + ext4_set_inode_state(inode, EXT4_STATE_XATTR); + return ext4_find_inline_data_nolock(inode); +diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c +index ff8916e1d38e9..af5a75a89e6e1 100644 +--- a/fs/ext4/migrate.c ++++ b/fs/ext4/migrate.c +@@ -417,7 +417,7 @@ int ext4_ext_migrate(struct inode *inode) + struct inode *tmp_inode = NULL; + struct migrate_struct lb; + unsigned long max_entries; +- __u32 goal; ++ __u32 goal, tmp_csum_seed; + uid_t owner[2]; + + /* +@@ -465,6 +465,7 @@ int ext4_ext_migrate(struct inode *inode) + * the migration. + */ + ei = EXT4_I(inode); ++ tmp_csum_seed = EXT4_I(tmp_inode)->i_csum_seed; + EXT4_I(tmp_inode)->i_csum_seed = ei->i_csum_seed; + i_size_write(tmp_inode, i_size_read(inode)); + /* +@@ -575,6 +576,7 @@ err_out: + * the inode is not visible to user space. + */ + tmp_inode->i_blocks = 0; ++ EXT4_I(tmp_inode)->i_csum_seed = tmp_csum_seed; + + /* Reset the extent details */ + ext4_ext_tree_init(handle, tmp_inode); +diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c +index 871eebf12bf42..5821638cb8937 100644 +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -54,6 +54,7 @@ static struct buffer_head *ext4_append(handle_t *handle, + struct inode *inode, + ext4_lblk_t *block) + { ++ struct ext4_map_blocks map; + struct buffer_head *bh; + int err; + +@@ -63,6 +64,21 @@ static struct buffer_head *ext4_append(handle_t *handle, + return ERR_PTR(-ENOSPC); + + *block = inode->i_size >> inode->i_sb->s_blocksize_bits; ++ map.m_lblk = *block; ++ map.m_len = 1; ++ ++ /* ++ * We're appending new directory block. Make sure the block is not ++ * allocated yet, otherwise we will end up corrupting the ++ * directory. ++ */ ++ err = ext4_map_blocks(NULL, inode, &map, 0); ++ if (err < 0) ++ return ERR_PTR(err); ++ if (err) { ++ EXT4_ERROR_INODE(inode, "Logical block already allocated"); ++ return ERR_PTR(-EFSCORRUPTED); ++ } + + bh = ext4_bread(handle, inode, *block, EXT4_GET_BLOCKS_CREATE); + if (IS_ERR(bh)) +@@ -110,6 +126,13 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode, + struct ext4_dir_entry *dirent; + int is_dx_block = 0; + ++ if (block >= inode->i_size) { ++ ext4_error_inode(inode, func, line, block, ++ "Attempting to read directory block (%u) that is past i_size (%llu)", ++ block, inode->i_size); ++ return ERR_PTR(-EFSCORRUPTED); ++ } ++ + if (ext4_simulate_fail(inode->i_sb, EXT4_SIM_DIRBLOCK_EIO)) + bh = ERR_PTR(-EIO); + else +diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c +index 56c9ef0687fcf..fa3c854125bbf 100644 +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -1472,6 +1472,7 @@ static void ext4_update_super(struct super_block *sb, + * Update the fs overhead information + */ + ext4_calculate_overhead(sb); ++ es->s_overhead_clusters = cpu_to_le32(sbi->s_overhead); + + if (test_opt(sb, DEBUG)) + printk(KERN_DEBUG "EXT4-fs: added group %u:" +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index 0423253490986..533216e80fa2b 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -436,6 +436,21 @@ error: + return err; + } + ++/* Remove entry from mbcache when EA inode is getting evicted */ ++void ext4_evict_ea_inode(struct inode *inode) ++{ ++ struct mb_cache_entry *oe; ++ ++ if (!EA_INODE_CACHE(inode)) ++ return; ++ /* Wait for entry to get unused so that we can remove it */ ++ while ((oe = mb_cache_entry_delete_or_get(EA_INODE_CACHE(inode), ++ ext4_xattr_inode_get_hash(inode), inode->i_ino))) { ++ mb_cache_entry_wait_unused(oe); ++ mb_cache_entry_put(EA_INODE_CACHE(inode), oe); ++ } ++} ++ + static int + ext4_xattr_inode_verify_hashes(struct inode *ea_inode, + struct ext4_xattr_entry *entry, void *buffer, +@@ -976,10 +991,8 @@ int __ext4_xattr_set_credits(struct super_block *sb, struct inode *inode, + static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode, + int ref_change) + { +- struct mb_cache *ea_inode_cache = EA_INODE_CACHE(ea_inode); + struct ext4_iloc iloc; + s64 ref_count; +- u32 hash; + int ret; + + inode_lock(ea_inode); +@@ -1002,14 +1015,6 @@ static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode, + + set_nlink(ea_inode, 1); + ext4_orphan_del(handle, ea_inode); +- +- if (ea_inode_cache) { +- hash = ext4_xattr_inode_get_hash(ea_inode); +- mb_cache_entry_create(ea_inode_cache, +- GFP_NOFS, hash, +- ea_inode->i_ino, +- true /* reusable */); +- } + } + } else { + WARN_ONCE(ref_count < 0, "EA inode %lu ref_count=%lld", +@@ -1022,12 +1027,6 @@ static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode, + + clear_nlink(ea_inode); + ext4_orphan_add(handle, ea_inode); +- +- if (ea_inode_cache) { +- hash = ext4_xattr_inode_get_hash(ea_inode); +- mb_cache_entry_delete(ea_inode_cache, hash, +- ea_inode->i_ino); +- } + } + } + +@@ -1237,6 +1236,7 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, + if (error) + goto out; + ++retry_ref: + lock_buffer(bh); + hash = le32_to_cpu(BHDR(bh)->h_hash); + ref = le32_to_cpu(BHDR(bh)->h_refcount); +@@ -1246,9 +1246,18 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, + * This must happen under buffer lock for + * ext4_xattr_block_set() to reliably detect freed block + */ +- if (ea_block_cache) +- mb_cache_entry_delete(ea_block_cache, hash, +- bh->b_blocknr); ++ if (ea_block_cache) { ++ struct mb_cache_entry *oe; ++ ++ oe = mb_cache_entry_delete_or_get(ea_block_cache, hash, ++ bh->b_blocknr); ++ if (oe) { ++ unlock_buffer(bh); ++ mb_cache_entry_wait_unused(oe); ++ mb_cache_entry_put(ea_block_cache, oe); ++ goto retry_ref; ++ } ++ } + get_bh(bh); + unlock_buffer(bh); + +@@ -1858,6 +1867,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, + #define header(x) ((struct ext4_xattr_header *)(x)) + + if (s->base) { ++ int offset = (char *)s->here - bs->bh->b_data; ++ + BUFFER_TRACE(bs->bh, "get_write_access"); + error = ext4_journal_get_write_access(handle, sb, bs->bh, + EXT4_JTR_NONE); +@@ -1873,9 +1884,20 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, + * ext4_xattr_block_set() to reliably detect modified + * block + */ +- if (ea_block_cache) +- mb_cache_entry_delete(ea_block_cache, hash, +- bs->bh->b_blocknr); ++ if (ea_block_cache) { ++ struct mb_cache_entry *oe; ++ ++ oe = mb_cache_entry_delete_or_get(ea_block_cache, ++ hash, bs->bh->b_blocknr); ++ if (oe) { ++ /* ++ * Xattr block is getting reused. Leave ++ * it alone. ++ */ ++ mb_cache_entry_put(ea_block_cache, oe); ++ goto clone_block; ++ } ++ } + ea_bdebug(bs->bh, "modifying in-place"); + error = ext4_xattr_set_entry(i, s, handle, inode, + true /* is_block */); +@@ -1890,50 +1912,47 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, + if (error) + goto cleanup; + goto inserted; +- } else { +- int offset = (char *)s->here - bs->bh->b_data; ++ } ++clone_block: ++ unlock_buffer(bs->bh); ++ ea_bdebug(bs->bh, "cloning"); ++ s->base = kmemdup(BHDR(bs->bh), bs->bh->b_size, GFP_NOFS); ++ error = -ENOMEM; ++ if (s->base == NULL) ++ goto cleanup; ++ s->first = ENTRY(header(s->base)+1); ++ header(s->base)->h_refcount = cpu_to_le32(1); ++ s->here = ENTRY(s->base + offset); ++ s->end = s->base + bs->bh->b_size; + +- unlock_buffer(bs->bh); +- ea_bdebug(bs->bh, "cloning"); +- s->base = kmalloc(bs->bh->b_size, GFP_NOFS); +- error = -ENOMEM; +- if (s->base == NULL) ++ /* ++ * If existing entry points to an xattr inode, we need ++ * to prevent ext4_xattr_set_entry() from decrementing ++ * ref count on it because the reference belongs to the ++ * original block. In this case, make the entry look ++ * like it has an empty value. ++ */ ++ if (!s->not_found && s->here->e_value_inum) { ++ ea_ino = le32_to_cpu(s->here->e_value_inum); ++ error = ext4_xattr_inode_iget(inode, ea_ino, ++ le32_to_cpu(s->here->e_hash), ++ &tmp_inode); ++ if (error) + goto cleanup; +- memcpy(s->base, BHDR(bs->bh), bs->bh->b_size); +- s->first = ENTRY(header(s->base)+1); +- header(s->base)->h_refcount = cpu_to_le32(1); +- s->here = ENTRY(s->base + offset); +- s->end = s->base + bs->bh->b_size; +- +- /* +- * If existing entry points to an xattr inode, we need +- * to prevent ext4_xattr_set_entry() from decrementing +- * ref count on it because the reference belongs to the +- * original block. In this case, make the entry look +- * like it has an empty value. +- */ +- if (!s->not_found && s->here->e_value_inum) { +- ea_ino = le32_to_cpu(s->here->e_value_inum); +- error = ext4_xattr_inode_iget(inode, ea_ino, +- le32_to_cpu(s->here->e_hash), +- &tmp_inode); +- if (error) +- goto cleanup; +- +- if (!ext4_test_inode_state(tmp_inode, +- EXT4_STATE_LUSTRE_EA_INODE)) { +- /* +- * Defer quota free call for previous +- * inode until success is guaranteed. +- */ +- old_ea_inode_quota = le32_to_cpu( +- s->here->e_value_size); +- } +- iput(tmp_inode); + +- s->here->e_value_inum = 0; +- s->here->e_value_size = 0; ++ if (!ext4_test_inode_state(tmp_inode, ++ EXT4_STATE_LUSTRE_EA_INODE)) { ++ /* ++ * Defer quota free call for previous ++ * inode until success is guaranteed. ++ */ ++ old_ea_inode_quota = le32_to_cpu( ++ s->here->e_value_size); + } ++ iput(tmp_inode); ++ ++ s->here->e_value_inum = 0; ++ s->here->e_value_size = 0; + } + } else { + /* Allocate a buffer where we construct the new block. */ +@@ -2000,18 +2019,13 @@ inserted: + lock_buffer(new_bh); + /* + * We have to be careful about races with +- * freeing, rehashing or adding references to +- * xattr block. Once we hold buffer lock xattr +- * block's state is stable so we can check +- * whether the block got freed / rehashed or +- * not. Since we unhash mbcache entry under +- * buffer lock when freeing / rehashing xattr +- * block, checking whether entry is still +- * hashed is reliable. Same rules hold for +- * e_reusable handling. ++ * adding references to xattr block. Once we ++ * hold buffer lock xattr block's state is ++ * stable so we can check the additional ++ * reference fits. + */ +- if (hlist_bl_unhashed(&ce->e_hash_list) || +- !ce->e_reusable) { ++ ref = le32_to_cpu(BHDR(new_bh)->h_refcount) + 1; ++ if (ref > EXT4_XATTR_REFCOUNT_MAX) { + /* + * Undo everything and check mbcache + * again. +@@ -2026,9 +2040,8 @@ inserted: + new_bh = NULL; + goto inserted; + } +- ref = le32_to_cpu(BHDR(new_bh)->h_refcount) + 1; + BHDR(new_bh)->h_refcount = cpu_to_le32(ref); +- if (ref >= EXT4_XATTR_REFCOUNT_MAX) ++ if (ref == EXT4_XATTR_REFCOUNT_MAX) + ce->e_reusable = 0; + ea_bdebug(new_bh, "reusing; refcount now=%d", + ref); +@@ -2176,8 +2189,9 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i, + struct ext4_inode *raw_inode; + int error; + +- if (EXT4_I(inode)->i_extra_isize == 0) ++ if (!EXT4_INODE_HAS_XATTR_SPACE(inode)) + return 0; ++ + raw_inode = ext4_raw_inode(&is->iloc); + header = IHDR(inode, raw_inode); + is->s.base = is->s.first = IFIRST(header); +@@ -2205,8 +2219,9 @@ int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode, + struct ext4_xattr_search *s = &is->s; + int error; + +- if (EXT4_I(inode)->i_extra_isize == 0) ++ if (!EXT4_INODE_HAS_XATTR_SPACE(inode)) + return -ENOSPC; ++ + error = ext4_xattr_set_entry(i, s, handle, inode, false /* is_block */); + if (error) + return error; +diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h +index 77efb9a627ad2..e5e36bd11f055 100644 +--- a/fs/ext4/xattr.h ++++ b/fs/ext4/xattr.h +@@ -95,6 +95,19 @@ struct ext4_xattr_entry { + + #define EXT4_ZERO_XATTR_VALUE ((void *)-1) + ++/* ++ * If we want to add an xattr to the inode, we should make sure that ++ * i_extra_isize is not 0 and that the inode size is not less than ++ * EXT4_GOOD_OLD_INODE_SIZE + extra_isize + pad. ++ * EXT4_GOOD_OLD_INODE_SIZE extra_isize header entry pad data ++ * |--------------------------|------------|------|---------|---|-------| ++ */ ++#define EXT4_INODE_HAS_XATTR_SPACE(inode) \ ++ ((EXT4_I(inode)->i_extra_isize != 0) && \ ++ (EXT4_GOOD_OLD_INODE_SIZE + EXT4_I(inode)->i_extra_isize + \ ++ sizeof(struct ext4_xattr_ibody_header) + EXT4_XATTR_PAD <= \ ++ EXT4_INODE_SIZE((inode)->i_sb))) ++ + struct ext4_xattr_info { + const char *name; + const void *value; +@@ -178,6 +191,7 @@ extern void ext4_xattr_inode_array_free(struct ext4_xattr_inode_array *array); + + extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, + struct ext4_inode *raw_inode, handle_t *handle); ++extern void ext4_evict_ea_inode(struct inode *inode); + + extern const struct xattr_handler *ext4_xattr_handlers[]; + +diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c +index bfcafc20eadab..758048a885d24 100644 +--- a/fs/f2fs/file.c ++++ b/fs/f2fs/file.c +@@ -1869,10 +1869,7 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask) + if (masked_flags & F2FS_COMPR_FL) { + if (!f2fs_disable_compressed_file(inode)) + return -EINVAL; +- } +- if (iflags & F2FS_NOCOMP_FL) +- return -EINVAL; +- if (iflags & F2FS_COMPR_FL) { ++ } else { + if (!f2fs_may_compress(inode)) + return -EINVAL; + if (S_ISREG(inode->i_mode) && inode->i_size) +@@ -1881,10 +1878,6 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask) + set_compress_context(inode); + } + } +- if ((iflags ^ masked_flags) & F2FS_NOCOMP_FL) { +- if (masked_flags & F2FS_COMPR_FL) +- return -EINVAL; +- } + + fi->i_flags = iflags | (fi->i_flags & ~mask); + f2fs_bug_on(F2FS_I_SB(inode), (fi->i_flags & F2FS_COMPR_FL) && +@@ -4018,8 +4011,8 @@ static int f2fs_ioc_decompress_file(struct file *filp, unsigned long arg) + goto out; + } + +- if (f2fs_is_mmap_file(inode)) { +- ret = -EBUSY; ++ if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) { ++ ret = -EINVAL; + goto out; + } + +@@ -4090,8 +4083,8 @@ static int f2fs_ioc_compress_file(struct file *filp, unsigned long arg) + goto out; + } + +- if (f2fs_is_mmap_file(inode)) { +- ret = -EBUSY; ++ if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) { ++ ret = -EINVAL; + goto out; + } + +diff --git a/fs/fuse/control.c b/fs/fuse/control.c +index 000d2e5627e99..79f01d09c78cb 100644 +--- a/fs/fuse/control.c ++++ b/fs/fuse/control.c +@@ -275,7 +275,7 @@ int fuse_ctl_add_conn(struct fuse_conn *fc) + struct dentry *parent; + char name[32]; + +- if (!fuse_control_sb) ++ if (!fuse_control_sb || fc->no_control) + return 0; + + parent = fuse_control_sb->s_root; +@@ -313,7 +313,7 @@ void fuse_ctl_remove_conn(struct fuse_conn *fc) + { + int i; + +- if (!fuse_control_sb) ++ if (!fuse_control_sb || fc->no_control) + return; + + for (i = fc->ctl_ndents - 1; i >= 0; i--) { +diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c +index 2f999d38c9b4a..50365143f50e8 100644 +--- a/fs/fuse/inode.c ++++ b/fs/fuse/inode.c +@@ -181,6 +181,12 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, + inode->i_uid = make_kuid(fc->user_ns, attr->uid); + inode->i_gid = make_kgid(fc->user_ns, attr->gid); + inode->i_blocks = attr->blocks; ++ ++ /* Sanitize nsecs */ ++ attr->atimensec = min_t(u32, attr->atimensec, NSEC_PER_SEC - 1); ++ attr->mtimensec = min_t(u32, attr->mtimensec, NSEC_PER_SEC - 1); ++ attr->ctimensec = min_t(u32, attr->ctimensec, NSEC_PER_SEC - 1); ++ + inode->i_atime.tv_sec = attr->atime; + inode->i_atime.tv_nsec = attr->atimensec; + /* mtime from server may be stale due to local buffered write */ +diff --git a/fs/fuse/ioctl.c b/fs/fuse/ioctl.c +index fc69e1797a331..e91d407038392 100644 +--- a/fs/fuse/ioctl.c ++++ b/fs/fuse/ioctl.c +@@ -9,6 +9,17 @@ + #include <linux/compat.h> + #include <linux/fileattr.h> + ++static ssize_t fuse_send_ioctl(struct fuse_mount *fm, struct fuse_args *args) ++{ ++ ssize_t ret = fuse_simple_request(fm, args); ++ ++ /* Translate ENOSYS, which shouldn't be returned from fs */ ++ if (ret == -ENOSYS) ++ ret = -ENOTTY; ++ ++ return ret; ++} ++ + /* + * CUSE servers compiled on 32bit broke on 64bit kernels because the + * ABI was defined to be 'struct iovec' which is different on 32bit +@@ -259,7 +270,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, + ap.args.out_pages = true; + ap.args.out_argvar = true; + +- transferred = fuse_simple_request(fm, &ap.args); ++ transferred = fuse_send_ioctl(fm, &ap.args); + err = transferred; + if (transferred < 0) + goto out; +@@ -393,7 +404,7 @@ static int fuse_priv_ioctl(struct inode *inode, struct fuse_file *ff, + args.out_args[1].size = inarg.out_size; + args.out_args[1].value = ptr; + +- err = fuse_simple_request(fm, &args); ++ err = fuse_send_ioctl(fm, &args); + if (!err) { + if (outarg.result < 0) + err = outarg.result; +diff --git a/fs/io_uring.c b/fs/io_uring.c +index 9bff14c5e2b26..0ce1587df4322 100644 +--- a/fs/io_uring.c ++++ b/fs/io_uring.c +@@ -4477,7 +4477,8 @@ static int io_provide_buffers(struct io_kiocb *req, unsigned int issue_flags) + + ret = io_add_buffers(p, &head); + if (ret >= 0 && !list) { +- ret = xa_insert(&ctx->io_buffers, p->bgid, head, GFP_KERNEL); ++ ret = xa_insert(&ctx->io_buffers, p->bgid, head, ++ GFP_KERNEL_ACCOUNT); + if (ret < 0) + __io_remove_buffers(ctx, head, p->bgid, -1U); + } +diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c +index 34b1406c06fde..69538061c5515 100644 +--- a/fs/jbd2/commit.c ++++ b/fs/jbd2/commit.c +@@ -564,13 +564,13 @@ void jbd2_journal_commit_transaction(journal_t *journal) + */ + jbd2_journal_switch_revoke_table(journal); + ++ write_lock(&journal->j_state_lock); + /* + * Reserved credits cannot be claimed anymore, free them + */ + atomic_sub(atomic_read(&journal->j_reserved_credits), + &commit_transaction->t_outstanding_credits); + +- write_lock(&journal->j_state_lock); + trace_jbd2_commit_flushing(journal, commit_transaction); + stats.run.rs_flushing = jiffies; + stats.run.rs_locked = jbd2_time_diff(stats.run.rs_locked, +diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c +index 6a3caedd22856..53cb236b53dbb 100644 +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -1477,8 +1477,6 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh) + struct journal_head *jh; + int ret = 0; + +- if (is_handle_aborted(handle)) +- return -EROFS; + if (!buffer_jbd(bh)) + return -EUCLEAN; + +@@ -1525,6 +1523,18 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh) + journal = transaction->t_journal; + spin_lock(&jh->b_state_lock); + ++ if (is_handle_aborted(handle)) { ++ /* ++ * Check journal aborting with @jh->b_state_lock locked, ++ * since 'jh->b_transaction' could be replaced with ++ * 'jh->b_next_transaction' during old transaction ++ * committing if journal aborted, which may fail ++ * assertion on 'jh->b_frozen_data == NULL'. ++ */ ++ ret = -EROFS; ++ goto out_unlock_bh; ++ } ++ + if (jh->b_modified == 0) { + /* + * This buffer's got modified and becoming part +diff --git a/fs/ksmbd/smb2misc.c b/fs/ksmbd/smb2misc.c +index 612ac15a7cf80..66b24b480ebf4 100644 +--- a/fs/ksmbd/smb2misc.c ++++ b/fs/ksmbd/smb2misc.c +@@ -91,11 +91,6 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len, + *off = 0; + *len = 0; + +- /* error reqeusts do not have data area */ +- if (hdr->Status && hdr->Status != STATUS_MORE_PROCESSING_REQUIRED && +- (((struct smb2_err_rsp *)hdr)->StructureSize) == SMB2_ERROR_STRUCTURE_SIZE2_LE) +- return ret; +- + /* + * Following commands have data areas so we have to get the location + * of the data buffer offset and data buffer length for the particular +diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c +index 876afde0ea660..53f5db40b96e8 100644 +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -1146,12 +1146,16 @@ int smb2_handle_negotiate(struct ksmbd_work *work) + status); + rsp->hdr.Status = status; + rc = -EINVAL; ++ kfree(conn->preauth_info); ++ conn->preauth_info = NULL; + goto err_out; + } + + rc = init_smb3_11_server(conn); + if (rc < 0) { + rsp->hdr.Status = STATUS_INVALID_PARAMETER; ++ kfree(conn->preauth_info); ++ conn->preauth_info = NULL; + goto err_out; + } + +@@ -2040,6 +2044,7 @@ int smb2_tree_disconnect(struct ksmbd_work *work) + + ksmbd_close_tree_conn_fds(work); + ksmbd_tree_conn_disconnect(sess, tcon); ++ work->tcon = NULL; + return 0; + } + +diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c +index e10ae2c41279e..1c9214801e69e 100644 +--- a/fs/lockd/svc4proc.c ++++ b/fs/lockd/svc4proc.c +@@ -32,6 +32,10 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, + if (!nlmsvc_ops) + return nlm_lck_denied_nolocks; + ++ if (lock->lock_start > OFFSET_MAX || ++ (lock->lock_len && ((lock->lock_len - 1) > (OFFSET_MAX - lock->lock_start)))) ++ return nlm4_fbig; ++ + /* Obtain host handle */ + if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len)) + || (argp->monitor && nsm_monitor(host) < 0)) +@@ -50,6 +54,10 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, + /* Set up the missing parts of the file_lock structure */ + lock->fl.fl_file = file->f_file[mode]; + lock->fl.fl_pid = current->tgid; ++ lock->fl.fl_start = (loff_t)lock->lock_start; ++ lock->fl.fl_end = lock->lock_len ? ++ (loff_t)(lock->lock_start + lock->lock_len - 1) : ++ OFFSET_MAX; + lock->fl.fl_lmops = &nlmsvc_lock_operations; + nlmsvc_locks_init_private(&lock->fl, host, (pid_t)lock->svid); + if (!lock->fl.fl_owner) { +diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c +index 98e957e4566c2..72f7d190fb3b2 100644 +--- a/fs/lockd/xdr4.c ++++ b/fs/lockd/xdr4.c +@@ -20,13 +20,6 @@ + + #include "svcxdr.h" + +-static inline loff_t +-s64_to_loff_t(__s64 offset) +-{ +- return (loff_t)offset; +-} +- +- + static inline s64 + loff_t_to_s64(loff_t offset) + { +@@ -70,8 +63,6 @@ static bool + svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock) + { + struct file_lock *fl = &lock->fl; +- u64 len, start; +- s64 end; + + if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len)) + return false; +@@ -81,20 +72,14 @@ svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock) + return false; + if (xdr_stream_decode_u32(xdr, &lock->svid) < 0) + return false; +- if (xdr_stream_decode_u64(xdr, &start) < 0) ++ if (xdr_stream_decode_u64(xdr, &lock->lock_start) < 0) + return false; +- if (xdr_stream_decode_u64(xdr, &len) < 0) ++ if (xdr_stream_decode_u64(xdr, &lock->lock_len) < 0) + return false; + + locks_init_lock(fl); + fl->fl_flags = FL_POSIX; + fl->fl_type = F_RDLCK; +- end = start + len - 1; +- fl->fl_start = s64_to_loff_t(start); +- if (len == 0 || end < 0) +- fl->fl_end = OFFSET_MAX; +- else +- fl->fl_end = s64_to_loff_t(end); + + return true; + } +diff --git a/fs/mbcache.c b/fs/mbcache.c +index 97c54d3a22276..2010bc80a3f2d 100644 +--- a/fs/mbcache.c ++++ b/fs/mbcache.c +@@ -11,7 +11,7 @@ + /* + * Mbcache is a simple key-value store. Keys need not be unique, however + * key-value pairs are expected to be unique (we use this fact in +- * mb_cache_entry_delete()). ++ * mb_cache_entry_delete_or_get()). + * + * Ext2 and ext4 use this cache for deduplication of extended attribute blocks. + * Ext4 also uses it for deduplication of xattr values stored in inodes. +@@ -125,6 +125,19 @@ void __mb_cache_entry_free(struct mb_cache_entry *entry) + } + EXPORT_SYMBOL(__mb_cache_entry_free); + ++/* ++ * mb_cache_entry_wait_unused - wait to be the last user of the entry ++ * ++ * @entry - entry to work on ++ * ++ * Wait to be the last user of the entry. ++ */ ++void mb_cache_entry_wait_unused(struct mb_cache_entry *entry) ++{ ++ wait_var_event(&entry->e_refcnt, atomic_read(&entry->e_refcnt) <= 3); ++} ++EXPORT_SYMBOL(mb_cache_entry_wait_unused); ++ + static struct mb_cache_entry *__entry_find(struct mb_cache *cache, + struct mb_cache_entry *entry, + u32 key) +@@ -217,7 +230,7 @@ out: + } + EXPORT_SYMBOL(mb_cache_entry_get); + +-/* mb_cache_entry_delete - remove a cache entry ++/* mb_cache_entry_delete - try to remove a cache entry + * @cache - cache we work with + * @key - key + * @value - value +@@ -254,6 +267,55 @@ void mb_cache_entry_delete(struct mb_cache *cache, u32 key, u64 value) + } + EXPORT_SYMBOL(mb_cache_entry_delete); + ++/* mb_cache_entry_delete_or_get - remove a cache entry if it has no users ++ * @cache - cache we work with ++ * @key - key ++ * @value - value ++ * ++ * Remove entry from cache @cache with key @key and value @value. The removal ++ * happens only if the entry is unused. The function returns NULL in case the ++ * entry was successfully removed or there's no entry in cache. Otherwise the ++ * function grabs reference of the entry that we failed to delete because it ++ * still has users and return it. ++ */ ++struct mb_cache_entry *mb_cache_entry_delete_or_get(struct mb_cache *cache, ++ u32 key, u64 value) ++{ ++ struct hlist_bl_node *node; ++ struct hlist_bl_head *head; ++ struct mb_cache_entry *entry; ++ ++ head = mb_cache_entry_head(cache, key); ++ hlist_bl_lock(head); ++ hlist_bl_for_each_entry(entry, node, head, e_hash_list) { ++ if (entry->e_key == key && entry->e_value == value) { ++ if (atomic_read(&entry->e_refcnt) > 2) { ++ atomic_inc(&entry->e_refcnt); ++ hlist_bl_unlock(head); ++ return entry; ++ } ++ /* We keep hash list reference to keep entry alive */ ++ hlist_bl_del_init(&entry->e_hash_list); ++ hlist_bl_unlock(head); ++ spin_lock(&cache->c_list_lock); ++ if (!list_empty(&entry->e_list)) { ++ list_del_init(&entry->e_list); ++ if (!WARN_ONCE(cache->c_entry_count == 0, ++ "mbcache: attempt to decrement c_entry_count past zero")) ++ cache->c_entry_count--; ++ atomic_dec(&entry->e_refcnt); ++ } ++ spin_unlock(&cache->c_list_lock); ++ mb_cache_entry_put(cache, entry); ++ return NULL; ++ } ++ } ++ hlist_bl_unlock(head); ++ ++ return NULL; ++} ++EXPORT_SYMBOL(mb_cache_entry_delete_or_get); ++ + /* mb_cache_entry_touch - cache entry got used + * @cache - cache the entry belongs to + * @entry - entry that got used +@@ -288,7 +350,7 @@ static unsigned long mb_cache_shrink(struct mb_cache *cache, + while (nr_to_scan-- && !list_empty(&cache->c_list)) { + entry = list_first_entry(&cache->c_list, + struct mb_cache_entry, e_list); +- if (entry->e_referenced) { ++ if (entry->e_referenced || atomic_read(&entry->e_refcnt) > 2) { + entry->e_referenced = 0; + list_move_tail(&entry->e_list, &cache->c_list); + continue; +@@ -302,6 +364,14 @@ static unsigned long mb_cache_shrink(struct mb_cache *cache, + spin_unlock(&cache->c_list_lock); + head = mb_cache_entry_head(cache, entry->e_key); + hlist_bl_lock(head); ++ /* Now a reliable check if the entry didn't get used... */ ++ if (atomic_read(&entry->e_refcnt) > 2) { ++ hlist_bl_unlock(head); ++ spin_lock(&cache->c_list_lock); ++ list_add_tail(&entry->e_list, &cache->c_list); ++ cache->c_entry_count++; ++ continue; ++ } + if (!hlist_bl_unhashed(&entry->e_hash_list)) { + hlist_bl_del_init(&entry->e_hash_list); + atomic_dec(&entry->e_refcnt); +diff --git a/fs/namei.c b/fs/namei.c +index 2ea15d043412a..1fd854d4cd2c0 100644 +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -1461,6 +1461,8 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, + * becoming unpinned. + */ + flags = dentry->d_flags; ++ if (read_seqretry(&mount_lock, nd->m_seq)) ++ return false; + continue; + } + if (read_seqretry(&mount_lock, nd->m_seq)) +@@ -3523,6 +3525,8 @@ struct dentry *vfs_tmpfile(struct user_namespace *mnt_userns, + child = d_alloc(dentry, &slash_name); + if (unlikely(!child)) + goto out_err; ++ if (!IS_POSIXACL(dir)) ++ mode &= ~current_umask(); + error = dir->i_op->tmpfile(mnt_userns, dir, child, mode); + if (error) + goto out_err; +diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c +index d383de00d4868..ceef75b4d2494 100644 +--- a/fs/nfs/flexfilelayout/flexfilelayout.c ++++ b/fs/nfs/flexfilelayout/flexfilelayout.c +@@ -1140,6 +1140,8 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task, + case -EIO: + case -ETIMEDOUT: + case -EPIPE: ++ case -EPROTO: ++ case -ENODEV: + dprintk("%s DS connection error %d\n", __func__, + task->tk_status); + nfs4_delete_deviceid(devid->ld, devid->nfs_client, +@@ -1245,6 +1247,8 @@ static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg, + case -ENOBUFS: + case -EPIPE: + case -EPERM: ++ case -EPROTO: ++ case -ENODEV: + *op_status = status = NFS4ERR_NXIO; + break; + case -EACCES: +diff --git a/fs/nfs/nfs3client.c b/fs/nfs/nfs3client.c +index 5601e47360c28..b49359afac883 100644 +--- a/fs/nfs/nfs3client.c ++++ b/fs/nfs/nfs3client.c +@@ -108,7 +108,6 @@ struct nfs_client *nfs3_set_ds_client(struct nfs_server *mds_srv, + if (mds_srv->flags & NFS_MOUNT_NORESVPORT) + __set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); + +- __set_bit(NFS_CS_NOPING, &cl_init.init_flags); + __set_bit(NFS_CS_DS, &cl_init.init_flags); + + /* Use the MDS nfs_client cl_ipaddr. */ +diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c +index 87d984e0cdc0c..1e8c31ed6c7c4 100644 +--- a/fs/nfsd/filecache.c ++++ b/fs/nfsd/filecache.c +@@ -187,12 +187,6 @@ nfsd_file_alloc(struct inode *inode, unsigned int may, unsigned int hashval, + nf->nf_hashval = hashval; + refcount_set(&nf->nf_ref, 1); + nf->nf_may = may & NFSD_FILE_MAY_MASK; +- if (may & NFSD_MAY_NOT_BREAK_LEASE) { +- if (may & NFSD_MAY_WRITE) +- __set_bit(NFSD_FILE_BREAK_WRITE, &nf->nf_flags); +- if (may & NFSD_MAY_READ) +- __set_bit(NFSD_FILE_BREAK_READ, &nf->nf_flags); +- } + nf->nf_mark = NULL; + trace_nfsd_file_alloc(nf); + } +@@ -990,21 +984,7 @@ wait_for_construction: + + this_cpu_inc(nfsd_file_cache_hits); + +- if (!(may_flags & NFSD_MAY_NOT_BREAK_LEASE)) { +- bool write = (may_flags & NFSD_MAY_WRITE); +- +- if (test_bit(NFSD_FILE_BREAK_READ, &nf->nf_flags) || +- (test_bit(NFSD_FILE_BREAK_WRITE, &nf->nf_flags) && write)) { +- status = nfserrno(nfsd_open_break_lease( +- file_inode(nf->nf_file), may_flags)); +- if (status == nfs_ok) { +- clear_bit(NFSD_FILE_BREAK_READ, &nf->nf_flags); +- if (write) +- clear_bit(NFSD_FILE_BREAK_WRITE, +- &nf->nf_flags); +- } +- } +- } ++ status = nfserrno(nfsd_open_break_lease(file_inode(nf->nf_file), may_flags)); + out: + if (status == nfs_ok) { + *pnf = nf; +diff --git a/fs/nfsd/filecache.h b/fs/nfsd/filecache.h +index 435ceab27897a..63104be2865c5 100644 +--- a/fs/nfsd/filecache.h ++++ b/fs/nfsd/filecache.h +@@ -37,9 +37,7 @@ struct nfsd_file { + struct net *nf_net; + #define NFSD_FILE_HASHED (0) + #define NFSD_FILE_PENDING (1) +-#define NFSD_FILE_BREAK_READ (2) +-#define NFSD_FILE_BREAK_WRITE (3) +-#define NFSD_FILE_REFERENCED (4) ++#define NFSD_FILE_REFERENCED (2) + unsigned long nf_flags; + struct inode *nf_inode; + unsigned int nf_hashval; +diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h +index b302836c7fdf9..0fc1fa6f28e0b 100644 +--- a/fs/nfsd/trace.h ++++ b/fs/nfsd/trace.h +@@ -636,18 +636,10 @@ DEFINE_CLID_EVENT(confirmed_r); + /* + * from fs/nfsd/filecache.h + */ +-TRACE_DEFINE_ENUM(NFSD_FILE_HASHED); +-TRACE_DEFINE_ENUM(NFSD_FILE_PENDING); +-TRACE_DEFINE_ENUM(NFSD_FILE_BREAK_READ); +-TRACE_DEFINE_ENUM(NFSD_FILE_BREAK_WRITE); +-TRACE_DEFINE_ENUM(NFSD_FILE_REFERENCED); +- + #define show_nf_flags(val) \ + __print_flags(val, "|", \ + { 1 << NFSD_FILE_HASHED, "HASHED" }, \ + { 1 << NFSD_FILE_PENDING, "PENDING" }, \ +- { 1 << NFSD_FILE_BREAK_READ, "BREAK_READ" }, \ +- { 1 << NFSD_FILE_BREAK_WRITE, "BREAK_WRITE" }, \ + { 1 << NFSD_FILE_REFERENCED, "REFERENCED"}) + + DECLARE_EVENT_CLASS(nfsd_file_class, +diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c +index ebde05c9cf62e..dbb944b5f81e5 100644 +--- a/fs/overlayfs/export.c ++++ b/fs/overlayfs/export.c +@@ -259,7 +259,7 @@ static int ovl_encode_fh(struct inode *inode, u32 *fid, int *max_len, + return FILEID_INVALID; + + dentry = d_find_any_alias(inode); +- if (WARN_ON(!dentry)) ++ if (!dentry) + return FILEID_INVALID; + + bytes = ovl_dentry_to_fid(ofs, dentry, fid, buflen); +diff --git a/fs/proc/base.c b/fs/proc/base.c +index 1f394095eb880..300d53ee7040c 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -1886,7 +1886,7 @@ void proc_pid_evict_inode(struct proc_inode *ei) + put_pid(pid); + } + +-struct inode *proc_pid_make_inode(struct super_block * sb, ++struct inode *proc_pid_make_inode(struct super_block *sb, + struct task_struct *task, umode_t mode) + { + struct inode * inode; +@@ -1915,11 +1915,6 @@ struct inode *proc_pid_make_inode(struct super_block * sb, + + /* Let the pid remember us for quick removal */ + ei->pid = pid; +- if (S_ISDIR(mode)) { +- spin_lock(&pid->lock); +- hlist_add_head_rcu(&ei->sibling_inodes, &pid->inodes); +- spin_unlock(&pid->lock); +- } + + task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid); + security_task_to_inode(task, inode); +@@ -1932,6 +1927,39 @@ out_unlock: + return NULL; + } + ++/* ++ * Generating an inode and adding it into @pid->inodes, so that task will ++ * invalidate inode's dentry before being released. ++ * ++ * This helper is used for creating dir-type entries under '/proc' and ++ * '/proc/<tgid>/task'. Other entries(eg. fd, stat) under '/proc/<tgid>' ++ * can be released by invalidating '/proc/<tgid>' dentry. ++ * In theory, dentries under '/proc/<tgid>/task' can also be released by ++ * invalidating '/proc/<tgid>' dentry, we reserve it to handle single ++ * thread exiting situation: Any one of threads should invalidate its ++ * '/proc/<tgid>/task/<pid>' dentry before released. ++ */ ++static struct inode *proc_pid_make_base_inode(struct super_block *sb, ++ struct task_struct *task, umode_t mode) ++{ ++ struct inode *inode; ++ struct proc_inode *ei; ++ struct pid *pid; ++ ++ inode = proc_pid_make_inode(sb, task, mode); ++ if (!inode) ++ return NULL; ++ ++ /* Let proc_flush_pid find this directory inode */ ++ ei = PROC_I(inode); ++ pid = ei->pid; ++ spin_lock(&pid->lock); ++ hlist_add_head_rcu(&ei->sibling_inodes, &pid->inodes); ++ spin_unlock(&pid->lock); ++ ++ return inode; ++} ++ + int pid_getattr(struct user_namespace *mnt_userns, const struct path *path, + struct kstat *stat, u32 request_mask, unsigned int query_flags) + { +@@ -3349,7 +3377,8 @@ static struct dentry *proc_pid_instantiate(struct dentry * dentry, + { + struct inode *inode; + +- inode = proc_pid_make_inode(dentry->d_sb, task, S_IFDIR | S_IRUGO | S_IXUGO); ++ inode = proc_pid_make_base_inode(dentry->d_sb, task, ++ S_IFDIR | S_IRUGO | S_IXUGO); + if (!inode) + return ERR_PTR(-ENOENT); + +@@ -3648,7 +3677,8 @@ static struct dentry *proc_task_instantiate(struct dentry *dentry, + struct task_struct *task, const void *ptr) + { + struct inode *inode; +- inode = proc_pid_make_inode(dentry->d_sb, task, S_IFDIR | S_IRUGO | S_IXUGO); ++ inode = proc_pid_make_base_inode(dentry->d_sb, task, ++ S_IFDIR | S_IRUGO | S_IXUGO); + if (!inode) + return ERR_PTR(-ENOENT); + +diff --git a/fs/splice.c b/fs/splice.c +index 5dbce4dcc1a7d..3abcd7fbc9f27 100644 +--- a/fs/splice.c ++++ b/fs/splice.c +@@ -814,17 +814,15 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, + { + struct pipe_inode_info *pipe; + long ret, bytes; +- umode_t i_mode; + size_t len; + int i, flags, more; + + /* +- * We require the input being a regular file, as we don't want to +- * randomly drop data for eg socket -> socket splicing. Use the +- * piped splicing for that! ++ * We require the input to be seekable, as we don't want to randomly ++ * drop data for eg socket -> socket splicing. Use the piped splicing ++ * for that! + */ +- i_mode = file_inode(in)->i_mode; +- if (unlikely(!S_ISREG(i_mode) && !S_ISBLK(i_mode))) ++ if (unlikely(!(in->f_mode & FMODE_LSEEK))) + return -EINVAL; + + /* +diff --git a/include/acpi/apei.h b/include/acpi/apei.h +index 680f80960c3dc..a6ac2e8b72da8 100644 +--- a/include/acpi/apei.h ++++ b/include/acpi/apei.h +@@ -27,14 +27,16 @@ extern int hest_disable; + extern int erst_disable; + #ifdef CONFIG_ACPI_APEI_GHES + extern bool ghes_disable; ++void __init ghes_init(void); + #else + #define ghes_disable 1 ++static inline void ghes_init(void) { } + #endif + + #ifdef CONFIG_ACPI_APEI + void __init acpi_hest_init(void); + #else +-static inline void acpi_hest_init(void) { return; } ++static inline void acpi_hest_init(void) { } + #endif + + typedef int (*apei_hest_func_t)(struct acpi_hest_header *hest_hdr, void *data); +diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h +index bc159a9b4a733..6b14414b9ec12 100644 +--- a/include/acpi/cppc_acpi.h ++++ b/include/acpi/cppc_acpi.h +@@ -17,7 +17,7 @@ + #include <acpi/pcc.h> + #include <acpi/processor.h> + +-/* Support CPPCv2 and CPPCv3 */ ++/* CPPCv2 and CPPCv3 support */ + #define CPPC_V2_REV 2 + #define CPPC_V3_REV 3 + #define CPPC_V2_NUM_ENT 21 +diff --git a/include/crypto/internal/blake2s.h b/include/crypto/internal/blake2s.h +index 52363eee2b20e..506d56530ca93 100644 +--- a/include/crypto/internal/blake2s.h ++++ b/include/crypto/internal/blake2s.h +@@ -8,7 +8,6 @@ + #define _CRYPTO_INTERNAL_BLAKE2S_H + + #include <crypto/blake2s.h> +-#include <crypto/internal/hash.h> + #include <linux/string.h> + + void blake2s_compress_generic(struct blake2s_state *state, const u8 *block, +@@ -19,111 +18,4 @@ void blake2s_compress(struct blake2s_state *state, const u8 *block, + + bool blake2s_selftest(void); + +-static inline void blake2s_set_lastblock(struct blake2s_state *state) +-{ +- state->f[0] = -1; +-} +- +-/* Helper functions for BLAKE2s shared by the library and shash APIs */ +- +-static __always_inline void +-__blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen, +- bool force_generic) +-{ +- const size_t fill = BLAKE2S_BLOCK_SIZE - state->buflen; +- +- if (unlikely(!inlen)) +- return; +- if (inlen > fill) { +- memcpy(state->buf + state->buflen, in, fill); +- if (force_generic) +- blake2s_compress_generic(state, state->buf, 1, +- BLAKE2S_BLOCK_SIZE); +- else +- blake2s_compress(state, state->buf, 1, +- BLAKE2S_BLOCK_SIZE); +- state->buflen = 0; +- in += fill; +- inlen -= fill; +- } +- if (inlen > BLAKE2S_BLOCK_SIZE) { +- const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2S_BLOCK_SIZE); +- /* Hash one less (full) block than strictly possible */ +- if (force_generic) +- blake2s_compress_generic(state, in, nblocks - 1, +- BLAKE2S_BLOCK_SIZE); +- else +- blake2s_compress(state, in, nblocks - 1, +- BLAKE2S_BLOCK_SIZE); +- in += BLAKE2S_BLOCK_SIZE * (nblocks - 1); +- inlen -= BLAKE2S_BLOCK_SIZE * (nblocks - 1); +- } +- memcpy(state->buf + state->buflen, in, inlen); +- state->buflen += inlen; +-} +- +-static __always_inline void +-__blake2s_final(struct blake2s_state *state, u8 *out, bool force_generic) +-{ +- blake2s_set_lastblock(state); +- memset(state->buf + state->buflen, 0, +- BLAKE2S_BLOCK_SIZE - state->buflen); /* Padding */ +- if (force_generic) +- blake2s_compress_generic(state, state->buf, 1, state->buflen); +- else +- blake2s_compress(state, state->buf, 1, state->buflen); +- cpu_to_le32_array(state->h, ARRAY_SIZE(state->h)); +- memcpy(out, state->h, state->outlen); +-} +- +-/* Helper functions for shash implementations of BLAKE2s */ +- +-struct blake2s_tfm_ctx { +- u8 key[BLAKE2S_KEY_SIZE]; +- unsigned int keylen; +-}; +- +-static inline int crypto_blake2s_setkey(struct crypto_shash *tfm, +- const u8 *key, unsigned int keylen) +-{ +- struct blake2s_tfm_ctx *tctx = crypto_shash_ctx(tfm); +- +- if (keylen == 0 || keylen > BLAKE2S_KEY_SIZE) +- return -EINVAL; +- +- memcpy(tctx->key, key, keylen); +- tctx->keylen = keylen; +- +- return 0; +-} +- +-static inline int crypto_blake2s_init(struct shash_desc *desc) +-{ +- const struct blake2s_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); +- struct blake2s_state *state = shash_desc_ctx(desc); +- unsigned int outlen = crypto_shash_digestsize(desc->tfm); +- +- __blake2s_init(state, outlen, tctx->key, tctx->keylen); +- return 0; +-} +- +-static inline int crypto_blake2s_update(struct shash_desc *desc, +- const u8 *in, unsigned int inlen, +- bool force_generic) +-{ +- struct blake2s_state *state = shash_desc_ctx(desc); +- +- __blake2s_update(state, in, inlen, force_generic); +- return 0; +-} +- +-static inline int crypto_blake2s_final(struct shash_desc *desc, u8 *out, +- bool force_generic) +-{ +- struct blake2s_state *state = shash_desc_ctx(desc); +- +- __blake2s_final(state, out, force_generic); +- return 0; +-} +- + #endif /* _CRYPTO_INTERNAL_BLAKE2S_H */ +diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h +index 46bdfa48c4134..9cdbd209388ed 100644 +--- a/include/drm/drm_bridge.h ++++ b/include/drm/drm_bridge.h +@@ -911,6 +911,8 @@ struct drm_bridge *devm_drm_panel_bridge_add(struct device *dev, + struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev, + struct drm_panel *panel, + u32 connector_type); ++struct drm_bridge *devm_drm_of_get_bridge(struct device *dev, struct device_node *node, ++ u32 port, u32 endpoint); + struct drm_connector *drm_panel_bridge_connector(struct drm_bridge *bridge); + #endif + +diff --git a/include/drm/drm_gem_shmem_helper.h b/include/drm/drm_gem_shmem_helper.h +index 434328d8a0d90..311d66c9cf4b1 100644 +--- a/include/drm/drm_gem_shmem_helper.h ++++ b/include/drm/drm_gem_shmem_helper.h +@@ -107,16 +107,17 @@ struct drm_gem_shmem_object { + container_of(obj, struct drm_gem_shmem_object, base) + + struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size); +-void drm_gem_shmem_free_object(struct drm_gem_object *obj); ++void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem); + + int drm_gem_shmem_get_pages(struct drm_gem_shmem_object *shmem); + void drm_gem_shmem_put_pages(struct drm_gem_shmem_object *shmem); +-int drm_gem_shmem_pin(struct drm_gem_object *obj); +-void drm_gem_shmem_unpin(struct drm_gem_object *obj); +-int drm_gem_shmem_vmap(struct drm_gem_object *obj, struct dma_buf_map *map); +-void drm_gem_shmem_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map); ++int drm_gem_shmem_pin(struct drm_gem_shmem_object *shmem); ++void drm_gem_shmem_unpin(struct drm_gem_shmem_object *shmem); ++int drm_gem_shmem_vmap(struct drm_gem_shmem_object *shmem, struct dma_buf_map *map); ++void drm_gem_shmem_vunmap(struct drm_gem_shmem_object *shmem, struct dma_buf_map *map); ++int drm_gem_shmem_mmap(struct drm_gem_shmem_object *shmem, struct vm_area_struct *vma); + +-int drm_gem_shmem_madvise(struct drm_gem_object *obj, int madv); ++int drm_gem_shmem_madvise(struct drm_gem_shmem_object *shmem, int madv); + + static inline bool drm_gem_shmem_is_purgeable(struct drm_gem_shmem_object *shmem) + { +@@ -125,29 +126,156 @@ static inline bool drm_gem_shmem_is_purgeable(struct drm_gem_shmem_object *shmem + !shmem->base.dma_buf && !shmem->base.import_attach; + } + +-void drm_gem_shmem_purge_locked(struct drm_gem_object *obj); +-bool drm_gem_shmem_purge(struct drm_gem_object *obj); ++void drm_gem_shmem_purge_locked(struct drm_gem_shmem_object *shmem); ++bool drm_gem_shmem_purge(struct drm_gem_shmem_object *shmem); + +-struct drm_gem_shmem_object * +-drm_gem_shmem_create_with_handle(struct drm_file *file_priv, +- struct drm_device *dev, size_t size, +- uint32_t *handle); ++struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_shmem_object *shmem); ++struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_shmem_object *shmem); + +-int drm_gem_shmem_dumb_create(struct drm_file *file, struct drm_device *dev, +- struct drm_mode_create_dumb *args); ++void drm_gem_shmem_print_info(const struct drm_gem_shmem_object *shmem, ++ struct drm_printer *p, unsigned int indent); ++ ++/* ++ * GEM object functions ++ */ ++ ++/** ++ * drm_gem_shmem_object_free - GEM object function for drm_gem_shmem_free() ++ * @obj: GEM object to free ++ * ++ * This function wraps drm_gem_shmem_free(). Drivers that employ the shmem helpers ++ * should use it as their &drm_gem_object_funcs.free handler. ++ */ ++static inline void drm_gem_shmem_object_free(struct drm_gem_object *obj) ++{ ++ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); ++ ++ drm_gem_shmem_free(shmem); ++} ++ ++/** ++ * drm_gem_shmem_object_print_info() - Print &drm_gem_shmem_object info for debugfs ++ * @p: DRM printer ++ * @indent: Tab indentation level ++ * @obj: GEM object ++ * ++ * This function wraps drm_gem_shmem_print_info(). Drivers that employ the shmem helpers should ++ * use this function as their &drm_gem_object_funcs.print_info handler. ++ */ ++static inline void drm_gem_shmem_object_print_info(struct drm_printer *p, unsigned int indent, ++ const struct drm_gem_object *obj) ++{ ++ const struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); ++ ++ drm_gem_shmem_print_info(shmem, p, indent); ++} ++ ++/** ++ * drm_gem_shmem_object_pin - GEM object function for drm_gem_shmem_pin() ++ * @obj: GEM object ++ * ++ * This function wraps drm_gem_shmem_pin(). Drivers that employ the shmem helpers should ++ * use it as their &drm_gem_object_funcs.pin handler. ++ */ ++static inline int drm_gem_shmem_object_pin(struct drm_gem_object *obj) ++{ ++ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); ++ ++ return drm_gem_shmem_pin(shmem); ++} ++ ++/** ++ * drm_gem_shmem_object_unpin - GEM object function for drm_gem_shmem_unpin() ++ * @obj: GEM object ++ * ++ * This function wraps drm_gem_shmem_unpin(). Drivers that employ the shmem helpers should ++ * use it as their &drm_gem_object_funcs.unpin handler. ++ */ ++static inline void drm_gem_shmem_object_unpin(struct drm_gem_object *obj) ++{ ++ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); ++ ++ drm_gem_shmem_unpin(shmem); ++} + +-int drm_gem_shmem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); ++/** ++ * drm_gem_shmem_object_get_sg_table - GEM object function for drm_gem_shmem_get_sg_table() ++ * @obj: GEM object ++ * ++ * This function wraps drm_gem_shmem_get_sg_table(). Drivers that employ the shmem helpers should ++ * use it as their &drm_gem_object_funcs.get_sg_table handler. ++ * ++ * Returns: ++ * A pointer to the scatter/gather table of pinned pages or NULL on failure. ++ */ ++static inline struct sg_table *drm_gem_shmem_object_get_sg_table(struct drm_gem_object *obj) ++{ ++ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); ++ ++ return drm_gem_shmem_get_sg_table(shmem); ++} ++ ++/* ++ * drm_gem_shmem_object_vmap - GEM object function for drm_gem_shmem_vmap() ++ * @obj: GEM object ++ * @map: Returns the kernel virtual address of the SHMEM GEM object's backing store. ++ * ++ * This function wraps drm_gem_shmem_vmap(). Drivers that employ the shmem helpers should ++ * use it as their &drm_gem_object_funcs.vmap handler. ++ * ++ * Returns: ++ * 0 on success or a negative error code on failure. ++ */ ++static inline int drm_gem_shmem_object_vmap(struct drm_gem_object *obj, struct dma_buf_map *map) ++{ ++ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); ++ ++ return drm_gem_shmem_vmap(shmem, map); ++} ++ ++/* ++ * drm_gem_shmem_object_vunmap - GEM object function for drm_gem_shmem_vunmap() ++ * @obj: GEM object ++ * @map: Kernel virtual address where the SHMEM GEM object was mapped ++ * ++ * This function wraps drm_gem_shmem_vunmap(). Drivers that employ the shmem helpers should ++ * use it as their &drm_gem_object_funcs.vunmap handler. ++ */ ++static inline void drm_gem_shmem_object_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map) ++{ ++ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); ++ ++ drm_gem_shmem_vunmap(shmem, map); ++} ++ ++/** ++ * drm_gem_shmem_object_mmap - GEM object function for drm_gem_shmem_mmap() ++ * @obj: GEM object ++ * @vma: VMA for the area to be mapped ++ * ++ * This function wraps drm_gem_shmem_mmap(). Drivers that employ the shmem helpers should ++ * use it as their &drm_gem_object_funcs.mmap handler. ++ * ++ * Returns: ++ * 0 on success or a negative error code on failure. ++ */ ++static inline int drm_gem_shmem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) ++{ ++ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); ++ ++ return drm_gem_shmem_mmap(shmem, vma); ++} + +-void drm_gem_shmem_print_info(struct drm_printer *p, unsigned int indent, +- const struct drm_gem_object *obj); ++/* ++ * Driver ops ++ */ + +-struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_object *obj); + struct drm_gem_object * + drm_gem_shmem_prime_import_sg_table(struct drm_device *dev, + struct dma_buf_attachment *attach, + struct sg_table *sgt); +- +-struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_object *obj); ++int drm_gem_shmem_dumb_create(struct drm_file *file, struct drm_device *dev, ++ struct drm_mode_create_dumb *args); + + /** + * DRM_GEM_SHMEM_DRIVER_OPS - Default shmem GEM operations +diff --git a/include/dt-bindings/clock/qcom,gcc-msm8939.h b/include/dt-bindings/clock/qcom,gcc-msm8939.h +index 0634467c4ce5a..2d545ed0d35ab 100644 +--- a/include/dt-bindings/clock/qcom,gcc-msm8939.h ++++ b/include/dt-bindings/clock/qcom,gcc-msm8939.h +@@ -192,6 +192,7 @@ + #define GCC_VENUS0_CORE0_VCODEC0_CLK 183 + #define GCC_VENUS0_CORE1_VCODEC0_CLK 184 + #define GCC_OXILI_TIMER_CLK 185 ++#define SYSTEM_MM_NOC_BFDCD_CLK_SRC 186 + + /* Indexes for GDSCs */ + #define BIMC_GDSC 0 +diff --git a/include/linux/acpi_viot.h b/include/linux/acpi_viot.h +index 1eb8ee5b0e5fe..a5a1224315637 100644 +--- a/include/linux/acpi_viot.h ++++ b/include/linux/acpi_viot.h +@@ -6,9 +6,11 @@ + #include <linux/acpi.h> + + #ifdef CONFIG_ACPI_VIOT ++void __init acpi_viot_early_init(void); + void __init acpi_viot_init(void); + int viot_iommu_configure(struct device *dev); + #else ++static inline void acpi_viot_early_init(void) {} + static inline void acpi_viot_init(void) {} + static inline int viot_iommu_configure(struct device *dev) + { +diff --git a/include/linux/arm_sdei.h b/include/linux/arm_sdei.h +index 0a241c5c911d8..14dc461b0e829 100644 +--- a/include/linux/arm_sdei.h ++++ b/include/linux/arm_sdei.h +@@ -46,9 +46,11 @@ int sdei_unregister_ghes(struct ghes *ghes); + /* For use by arch code when CPU hotplug notifiers are not appropriate. */ + int sdei_mask_local_cpu(void); + int sdei_unmask_local_cpu(void); ++void __init sdei_init(void); + #else + static inline int sdei_mask_local_cpu(void) { return 0; } + static inline int sdei_unmask_local_cpu(void) { return 0; } ++static inline void sdei_init(void) { } + #endif /* CONFIG_ARM_SDE_INTERFACE */ + + +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index aebe67ed7a73e..8863b4a378afe 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -261,8 +261,6 @@ static inline unsigned short req_get_ioprio(struct request *req) + + #include <linux/elevator.h> + +-struct blk_queue_ctx; +- + struct bio_vec; + + enum blk_eh_timer_return { +diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h +index 36f33685c8c00..c841367ff8c95 100644 +--- a/include/linux/buffer_head.h ++++ b/include/linux/buffer_head.h +@@ -117,7 +117,6 @@ static __always_inline int test_clear_buffer_##name(struct buffer_head *bh) \ + * of the form "mark_buffer_foo()". These are higher-level functions which + * do something in addition to setting a b_state bit. + */ +-BUFFER_FNS(Uptodate, uptodate) + BUFFER_FNS(Dirty, dirty) + TAS_BUFFER_FNS(Dirty, dirty) + BUFFER_FNS(Lock, locked) +@@ -135,6 +134,30 @@ BUFFER_FNS(Meta, meta) + BUFFER_FNS(Prio, prio) + BUFFER_FNS(Defer_Completion, defer_completion) + ++static __always_inline void set_buffer_uptodate(struct buffer_head *bh) ++{ ++ /* ++ * make it consistent with folio_mark_uptodate ++ * pairs with smp_load_acquire in buffer_uptodate ++ */ ++ smp_mb__before_atomic(); ++ set_bit(BH_Uptodate, &bh->b_state); ++} ++ ++static __always_inline void clear_buffer_uptodate(struct buffer_head *bh) ++{ ++ clear_bit(BH_Uptodate, &bh->b_state); ++} ++ ++static __always_inline int buffer_uptodate(const struct buffer_head *bh) ++{ ++ /* ++ * make it consistent with folio_test_uptodate ++ * pairs with smp_mb__before_atomic in set_buffer_uptodate ++ */ ++ return (smp_load_acquire(&bh->b_state) & (1UL << BH_Uptodate)) != 0; ++} ++ + #define bh_offset(bh) ((unsigned long)(bh)->b_data & ~PAGE_MASK) + + /* If we *know* page->private refers to buffer_heads */ +diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h +index 694264503119d..00ed7c17698d1 100644 +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -1023,6 +1023,8 @@ struct ieee80211_tpc_report_ie { + #define IEEE80211_ADDBA_EXT_FRAG_LEVEL_MASK GENMASK(2, 1) + #define IEEE80211_ADDBA_EXT_FRAG_LEVEL_SHIFT 1 + #define IEEE80211_ADDBA_EXT_NO_FRAG BIT(0) ++#define IEEE80211_ADDBA_EXT_BUF_SIZE_MASK GENMASK(7, 5) ++#define IEEE80211_ADDBA_EXT_BUF_SIZE_SHIFT 10 + + struct ieee80211_addba_ext_ie { + u8 data; +@@ -1697,10 +1699,12 @@ struct ieee80211_ht_operation { + * A-MPDU buffer sizes + * According to HT size varies from 8 to 64 frames + * HE adds the ability to have up to 256 frames. ++ * EHT adds the ability to have up to 1K frames. + */ + #define IEEE80211_MIN_AMPDU_BUF 0x8 + #define IEEE80211_MAX_AMPDU_BUF_HT 0x40 +-#define IEEE80211_MAX_AMPDU_BUF 0x100 ++#define IEEE80211_MAX_AMPDU_BUF_HE 0x100 ++#define IEEE80211_MAX_AMPDU_BUF_EHT 0x400 + + + /* Spatial Multiplexing Power Save Modes (for capability) */ +diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h +index c582e1a142320..7b5dbd7499957 100644 +--- a/include/linux/iio/common/cros_ec_sensors_core.h ++++ b/include/linux/iio/common/cros_ec_sensors_core.h +@@ -95,8 +95,11 @@ int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev, unsigned long scan_mask, + struct platform_device; + int cros_ec_sensors_core_init(struct platform_device *pdev, + struct iio_dev *indio_dev, bool physical_device, +- cros_ec_sensors_capture_t trigger_capture, +- cros_ec_sensorhub_push_data_cb_t push_data); ++ cros_ec_sensors_capture_t trigger_capture); ++ ++int cros_ec_sensors_core_register(struct device *dev, ++ struct iio_dev *indio_dev, ++ cros_ec_sensorhub_push_data_cb_t push_data); + + irqreturn_t cros_ec_sensors_capture(int irq, void *p); + int cros_ec_sensors_push_data(struct iio_dev *indio_dev, +diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h +index 86249476b57f4..0b35a41440ff1 100644 +--- a/include/linux/kfifo.h ++++ b/include/linux/kfifo.h +@@ -688,7 +688,7 @@ __kfifo_uint_must_check_helper( \ + * writer, you don't need extra locking to use these macro. + */ + #define kfifo_to_user(fifo, to, len, copied) \ +-__kfifo_uint_must_check_helper( \ ++__kfifo_int_must_check_helper( \ + ({ \ + typeof((fifo) + 1) __tmp = (fifo); \ + void __user *__to = (to); \ +diff --git a/include/linux/lockd/xdr.h b/include/linux/lockd/xdr.h +index a98309c0121cb..bed63156b0521 100644 +--- a/include/linux/lockd/xdr.h ++++ b/include/linux/lockd/xdr.h +@@ -41,6 +41,8 @@ struct nlm_lock { + struct nfs_fh fh; + struct xdr_netobj oh; + u32 svid; ++ u64 lock_start; ++ u64 lock_len; + struct file_lock fl; + }; + +diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h +index 9fe165beb0f9e..aa0ecfc6cdb4b 100644 +--- a/include/linux/lockdep.h ++++ b/include/linux/lockdep.h +@@ -192,7 +192,7 @@ static inline void + lockdep_init_map_waits(struct lockdep_map *lock, const char *name, + struct lock_class_key *key, int subclass, u8 inner, u8 outer) + { +- lockdep_init_map_type(lock, name, key, subclass, inner, LD_WAIT_INV, LD_LOCK_NORMAL); ++ lockdep_init_map_type(lock, name, key, subclass, inner, outer, LD_LOCK_NORMAL); + } + + static inline void +@@ -215,24 +215,28 @@ static inline void lockdep_init_map(struct lockdep_map *lock, const char *name, + * or they are too narrow (they suffer from a false class-split): + */ + #define lockdep_set_class(lock, key) \ +- lockdep_init_map_waits(&(lock)->dep_map, #key, key, 0, \ +- (lock)->dep_map.wait_type_inner, \ +- (lock)->dep_map.wait_type_outer) ++ lockdep_init_map_type(&(lock)->dep_map, #key, key, 0, \ ++ (lock)->dep_map.wait_type_inner, \ ++ (lock)->dep_map.wait_type_outer, \ ++ (lock)->dep_map.lock_type) + + #define lockdep_set_class_and_name(lock, key, name) \ +- lockdep_init_map_waits(&(lock)->dep_map, name, key, 0, \ +- (lock)->dep_map.wait_type_inner, \ +- (lock)->dep_map.wait_type_outer) ++ lockdep_init_map_type(&(lock)->dep_map, name, key, 0, \ ++ (lock)->dep_map.wait_type_inner, \ ++ (lock)->dep_map.wait_type_outer, \ ++ (lock)->dep_map.lock_type) + + #define lockdep_set_class_and_subclass(lock, key, sub) \ +- lockdep_init_map_waits(&(lock)->dep_map, #key, key, sub,\ +- (lock)->dep_map.wait_type_inner, \ +- (lock)->dep_map.wait_type_outer) ++ lockdep_init_map_type(&(lock)->dep_map, #key, key, sub, \ ++ (lock)->dep_map.wait_type_inner, \ ++ (lock)->dep_map.wait_type_outer, \ ++ (lock)->dep_map.lock_type) + + #define lockdep_set_subclass(lock, sub) \ +- lockdep_init_map_waits(&(lock)->dep_map, #lock, (lock)->dep_map.key, sub,\ +- (lock)->dep_map.wait_type_inner, \ +- (lock)->dep_map.wait_type_outer) ++ lockdep_init_map_type(&(lock)->dep_map, #lock, (lock)->dep_map.key, sub,\ ++ (lock)->dep_map.wait_type_inner, \ ++ (lock)->dep_map.wait_type_outer, \ ++ (lock)->dep_map.lock_type) + + #define lockdep_set_novalidate_class(lock) \ + lockdep_set_class_and_name(lock, &__lockdep_no_validate__, #lock) +diff --git a/include/linux/mbcache.h b/include/linux/mbcache.h +index 20f1e3ff60130..8eca7f25c4320 100644 +--- a/include/linux/mbcache.h ++++ b/include/linux/mbcache.h +@@ -30,15 +30,23 @@ void mb_cache_destroy(struct mb_cache *cache); + int mb_cache_entry_create(struct mb_cache *cache, gfp_t mask, u32 key, + u64 value, bool reusable); + void __mb_cache_entry_free(struct mb_cache_entry *entry); ++void mb_cache_entry_wait_unused(struct mb_cache_entry *entry); + static inline int mb_cache_entry_put(struct mb_cache *cache, + struct mb_cache_entry *entry) + { +- if (!atomic_dec_and_test(&entry->e_refcnt)) ++ unsigned int cnt = atomic_dec_return(&entry->e_refcnt); ++ ++ if (cnt > 0) { ++ if (cnt <= 3) ++ wake_up_var(&entry->e_refcnt); + return 0; ++ } + __mb_cache_entry_free(entry); + return 1; + } + ++struct mb_cache_entry *mb_cache_entry_delete_or_get(struct mb_cache *cache, ++ u32 key, u64 value); + void mb_cache_entry_delete(struct mb_cache *cache, u32 key, u64 value); + struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *cache, u32 key, + u64 value); +diff --git a/include/linux/memremap.h b/include/linux/memremap.h +index c0e9d35889e8d..a8bc588fe7aa8 100644 +--- a/include/linux/memremap.h ++++ b/include/linux/memremap.h +@@ -72,16 +72,6 @@ struct dev_pagemap_ops { + */ + void (*page_free)(struct page *page); + +- /* +- * Transition the refcount in struct dev_pagemap to the dead state. +- */ +- void (*kill)(struct dev_pagemap *pgmap); +- +- /* +- * Wait for refcount in struct dev_pagemap to be idle and reap it. +- */ +- void (*cleanup)(struct dev_pagemap *pgmap); +- + /* + * Used for private (un-addressable) device memory only. Must migrate + * the page back to a CPU accessible page. +@@ -95,8 +85,7 @@ struct dev_pagemap_ops { + * struct dev_pagemap - metadata for ZONE_DEVICE mappings + * @altmap: pre-allocated/reserved memory for vmemmap allocations + * @ref: reference count that pins the devm_memremap_pages() mapping +- * @internal_ref: internal reference if @ref is not provided by the caller +- * @done: completion for @internal_ref ++ * @done: completion for @ref + * @type: memory type: see MEMORY_* in memory_hotplug.h + * @flags: PGMAP_* flags to specify defailed behavior + * @ops: method table +@@ -109,8 +98,7 @@ struct dev_pagemap_ops { + */ + struct dev_pagemap { + struct vmem_altmap altmap; +- struct percpu_ref *ref; +- struct percpu_ref internal_ref; ++ struct percpu_ref ref; + struct completion done; + enum memory_type type; + unsigned int flags; +@@ -191,7 +179,7 @@ static inline unsigned long memremap_compat_align(void) + static inline void put_dev_pagemap(struct dev_pagemap *pgmap) + { + if (pgmap) +- percpu_ref_put(pgmap->ref); ++ percpu_ref_put(&pgmap->ref); + } + + #endif /* _LINUX_MEMREMAP_H_ */ +diff --git a/include/linux/mfd/t7l66xb.h b/include/linux/mfd/t7l66xb.h +index 69632c1b07bd8..ae3e7a5c5219b 100644 +--- a/include/linux/mfd/t7l66xb.h ++++ b/include/linux/mfd/t7l66xb.h +@@ -12,7 +12,6 @@ + + struct t7l66xb_platform_data { + int (*enable)(struct platform_device *dev); +- int (*disable)(struct platform_device *dev); + int (*suspend)(struct platform_device *dev); + int (*resume)(struct platform_device *dev); + +diff --git a/include/linux/once_lite.h b/include/linux/once_lite.h +index 861e606b820fa..b7bce4983638f 100644 +--- a/include/linux/once_lite.h ++++ b/include/linux/once_lite.h +@@ -9,15 +9,27 @@ + */ + #define DO_ONCE_LITE(func, ...) \ + DO_ONCE_LITE_IF(true, func, ##__VA_ARGS__) +-#define DO_ONCE_LITE_IF(condition, func, ...) \ ++ ++#define __ONCE_LITE_IF(condition) \ + ({ \ + static bool __section(".data.once") __already_done; \ +- bool __ret_do_once = !!(condition); \ ++ bool __ret_cond = !!(condition); \ ++ bool __ret_once = false; \ + \ +- if (unlikely(__ret_do_once && !__already_done)) { \ ++ if (unlikely(__ret_cond && !__already_done)) { \ + __already_done = true; \ +- func(__VA_ARGS__); \ ++ __ret_once = true; \ + } \ ++ unlikely(__ret_once); \ ++ }) ++ ++#define DO_ONCE_LITE_IF(condition, func, ...) \ ++ ({ \ ++ bool __ret_do_once = !!(condition); \ ++ \ ++ if (__ONCE_LITE_IF(__ret_do_once)) \ ++ func(__VA_ARGS__); \ ++ \ + unlikely(__ret_do_once); \ + }) + +diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h +index 011f2f1ea5bb5..04f44a4694a2e 100644 +--- a/include/linux/pci_ids.h ++++ b/include/linux/pci_ids.h +@@ -60,6 +60,8 @@ + #define PCI_CLASS_BRIDGE_EISA 0x0602 + #define PCI_CLASS_BRIDGE_MC 0x0603 + #define PCI_CLASS_BRIDGE_PCI 0x0604 ++#define PCI_CLASS_BRIDGE_PCI_NORMAL 0x060400 ++#define PCI_CLASS_BRIDGE_PCI_SUBTRACTIVE 0x060401 + #define PCI_CLASS_BRIDGE_PCMCIA 0x0605 + #define PCI_CLASS_BRIDGE_NUBUS 0x0606 + #define PCI_CLASS_BRIDGE_CARDBUS 0x0607 +diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h +index c0b6ec6bf65b7..18dcca51829e2 100644 +--- a/include/linux/pipe_fs_i.h ++++ b/include/linux/pipe_fs_i.h +@@ -229,6 +229,15 @@ static inline bool pipe_buf_try_steal(struct pipe_inode_info *pipe, + return buf->ops->try_steal(pipe, buf); + } + ++static inline void pipe_discard_from(struct pipe_inode_info *pipe, ++ unsigned int old_head) ++{ ++ unsigned int mask = pipe->ring_size - 1; ++ ++ while (pipe->head > old_head) ++ pipe_buf_release(pipe, &pipe->bufs[--pipe->head & mask]); ++} ++ + /* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual + memory allocation, whereas PIPE_BUF makes atomicity guarantees. */ + #define PIPE_SIZE PAGE_SIZE +diff --git a/include/linux/sched.h b/include/linux/sched.h +index ad7ff332a0ac8..dcba347cbffa1 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -1797,7 +1797,7 @@ current_restore_flags(unsigned long orig_flags, unsigned long flags) + } + + extern int cpuset_cpumask_can_shrink(const struct cpumask *cur, const struct cpumask *trial); +-extern int task_can_attach(struct task_struct *p, const struct cpumask *cs_cpus_allowed); ++extern int task_can_attach(struct task_struct *p, const struct cpumask *cs_effective_cpus); + #ifdef CONFIG_SMP + extern void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask); + extern int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask); +diff --git a/include/linux/sched/rt.h b/include/linux/sched/rt.h +index e5af028c08b49..994c25640e156 100644 +--- a/include/linux/sched/rt.h ++++ b/include/linux/sched/rt.h +@@ -39,20 +39,12 @@ static inline struct task_struct *rt_mutex_get_top_task(struct task_struct *p) + } + extern void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task); + extern void rt_mutex_adjust_pi(struct task_struct *p); +-static inline bool tsk_is_pi_blocked(struct task_struct *tsk) +-{ +- return tsk->pi_blocked_on != NULL; +-} + #else + static inline struct task_struct *rt_mutex_get_top_task(struct task_struct *task) + { + return NULL; + } + # define rt_mutex_adjust_pi(p) do { } while (0) +-static inline bool tsk_is_pi_blocked(struct task_struct *tsk) +-{ +- return false; +-} + #endif + + extern void normalize_rt_tasks(void); +diff --git a/include/linux/sched/topology.h b/include/linux/sched/topology.h +index 8f0f778b7c911..63a04a65e3106 100644 +--- a/include/linux/sched/topology.h ++++ b/include/linux/sched/topology.h +@@ -74,6 +74,7 @@ struct sched_domain_shared { + atomic_t ref; + atomic_t nr_busy_cpus; + int has_idle_cores; ++ int nr_idle_scan; + }; + + struct sched_domain { +diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h +index 76ce3f3ac0f22..bf6f0decb3f6d 100644 +--- a/include/linux/soundwire/sdw.h ++++ b/include/linux/soundwire/sdw.h +@@ -646,9 +646,6 @@ struct sdw_slave_ops { + * @dev_num: Current Device Number, values can be 0 or dev_num_sticky + * @dev_num_sticky: one-time static Device Number assigned by Bus + * @probed: boolean tracking driver state +- * @probe_complete: completion utility to control potential races +- * on startup between driver probe/initialization and SoundWire +- * Slave state changes/implementation-defined interrupts + * @enumeration_complete: completion utility to control potential races + * on startup between device enumeration and read/write access to the + * Slave device +@@ -663,6 +660,7 @@ struct sdw_slave_ops { + * for a Slave happens for the first time after enumeration + * @is_mockup_device: status flag used to squelch errors in the command/control + * protocol for SoundWire mockup devices ++ * @sdw_dev_lock: mutex used to protect callbacks/remove races + */ + struct sdw_slave { + struct sdw_slave_id id; +@@ -680,12 +678,12 @@ struct sdw_slave { + u16 dev_num; + u16 dev_num_sticky; + bool probed; +- struct completion probe_complete; + struct completion enumeration_complete; + struct completion initialization_complete; + u32 unattach_request; + bool first_interrupt_done; + bool is_mockup_device; ++ struct mutex sdw_dev_lock; /* protect callbacks/remove races */ + }; + + #define dev_to_sdw_dev(_dev) container_of(_dev, struct sdw_slave, dev) +diff --git a/include/linux/torture.h b/include/linux/torture.h +index 0910c5803f35a..24f58e50a94b8 100644 +--- a/include/linux/torture.h ++++ b/include/linux/torture.h +@@ -47,6 +47,14 @@ do { \ + } while (0) + void verbose_torout_sleep(void); + ++#define torture_init_error(firsterr) \ ++({ \ ++ int ___firsterr = (firsterr); \ ++ \ ++ WARN_ONCE(!IS_MODULE(CONFIG_RCU_TORTURE_TEST) && ___firsterr < 0, "Torture-test initialization failed with error code %d\n", ___firsterr); \ ++ ___firsterr < 0; \ ++}) ++ + /* Definitions for online/offline exerciser. */ + #ifdef CONFIG_HOTPLUG_CPU + int torture_num_online_cpus(void); +diff --git a/include/linux/tpm_eventlog.h b/include/linux/tpm_eventlog.h +index 739ba9a03ec16..20c0ff54b7a0d 100644 +--- a/include/linux/tpm_eventlog.h ++++ b/include/linux/tpm_eventlog.h +@@ -157,7 +157,7 @@ struct tcg_algorithm_info { + * Return: size of the event on success, 0 on failure + */ + +-static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event, ++static __always_inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event, + struct tcg_pcr_event *event_header, + bool do_mapping) + { +diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h +index 2c1fc9212cf28..98d1921f02b1e 100644 +--- a/include/linux/usb/hcd.h ++++ b/include/linux/usb/hcd.h +@@ -66,6 +66,7 @@ + + struct giveback_urb_bh { + bool running; ++ bool high_prio; + spinlock_t lock; + struct list_head head; + struct tasklet_struct bh; +diff --git a/include/linux/wait.h b/include/linux/wait.h +index d22cf2985b8fd..21044562aab74 100644 +--- a/include/linux/wait.h ++++ b/include/linux/wait.h +@@ -544,10 +544,11 @@ do { \ + \ + hrtimer_init_sleeper_on_stack(&__t, CLOCK_MONOTONIC, \ + HRTIMER_MODE_REL); \ +- if ((timeout) != KTIME_MAX) \ +- hrtimer_start_range_ns(&__t.timer, timeout, \ +- current->timer_slack_ns, \ +- HRTIMER_MODE_REL); \ ++ if ((timeout) != KTIME_MAX) { \ ++ hrtimer_set_expires_range_ns(&__t.timer, timeout, \ ++ current->timer_slack_ns); \ ++ hrtimer_sleeper_start_expires(&__t, HRTIMER_MODE_REL); \ ++ } \ + \ + __ret = ___wait_event(wq_head, condition, state, 0, 0, \ + if (!__t.task) { \ +diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h +index 03614de869425..6d0615140dbcf 100644 +--- a/include/net/9p/9p.h ++++ b/include/net/9p/9p.h +@@ -32,13 +32,13 @@ + */ + + enum p9_debug_flags { +- P9_DEBUG_ERROR = (1<<0), +- P9_DEBUG_9P = (1<<2), ++ P9_DEBUG_ERROR = (1<<0), ++ P9_DEBUG_9P = (1<<2), + P9_DEBUG_VFS = (1<<3), + P9_DEBUG_CONV = (1<<4), + P9_DEBUG_MUX = (1<<5), + P9_DEBUG_TRANS = (1<<6), +- P9_DEBUG_SLABS = (1<<7), ++ P9_DEBUG_SLABS = (1<<7), + P9_DEBUG_FCALL = (1<<8), + P9_DEBUG_FID = (1<<9), + P9_DEBUG_PKT = (1<<10), +@@ -317,8 +317,8 @@ enum p9_qid_t { + }; + + /* 9P Magic Numbers */ +-#define P9_NOTAG (u16)(~0) +-#define P9_NOFID (u32)(~0) ++#define P9_NOTAG ((u16)(~0)) ++#define P9_NOFID ((u32)(~0)) + #define P9_MAXWELEM 16 + + /* Minimal header size: size[4] type[1] tag[2] */ +diff --git a/include/net/9p/client.h b/include/net/9p/client.h +index e1c308d8d288e..7060de84c5593 100644 +--- a/include/net/9p/client.h ++++ b/include/net/9p/client.h +@@ -23,7 +23,7 @@ + * @p9_proto_2000L: 9P2000.L extension + */ + +-enum p9_proto_versions{ ++enum p9_proto_versions { + p9_proto_legacy, + p9_proto_2000u, + p9_proto_2000L, +@@ -78,7 +78,7 @@ enum p9_req_status_t { + struct p9_req_t { + int status; + int t_err; +- struct kref refcount; ++ refcount_t refcount; + wait_queue_head_t wq; + struct p9_fcall tc; + struct p9_fcall rc; +@@ -219,36 +219,40 @@ struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid, + u64 request_mask); + + int p9_client_mknod_dotl(struct p9_fid *oldfid, const char *name, int mode, +- dev_t rdev, kgid_t gid, struct p9_qid *); ++ dev_t rdev, kgid_t gid, struct p9_qid *qid); + int p9_client_mkdir_dotl(struct p9_fid *fid, const char *name, int mode, +- kgid_t gid, struct p9_qid *); ++ kgid_t gid, struct p9_qid *qid); + int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status); + int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *fl); + void p9_fcall_fini(struct p9_fcall *fc); +-struct p9_req_t *p9_tag_lookup(struct p9_client *, u16); ++struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag); + + static inline void p9_req_get(struct p9_req_t *r) + { +- kref_get(&r->refcount); ++ refcount_inc(&r->refcount); + } + + static inline int p9_req_try_get(struct p9_req_t *r) + { +- return kref_get_unless_zero(&r->refcount); ++ return refcount_inc_not_zero(&r->refcount); + } + +-int p9_req_put(struct p9_req_t *r); ++int p9_req_put(struct p9_client *c, struct p9_req_t *r); + + void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status); + +-int p9_parse_header(struct p9_fcall *, int32_t *, int8_t *, int16_t *, int); +-int p9stat_read(struct p9_client *, char *, int, struct p9_wstat *); +-void p9stat_free(struct p9_wstat *); ++int p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type, ++ int16_t *tag, int rewind); ++int p9stat_read(struct p9_client *clnt, char *buf, int len, ++ struct p9_wstat *st); ++void p9stat_free(struct p9_wstat *stbuf); + + int p9_is_proto_dotu(struct p9_client *clnt); + int p9_is_proto_dotl(struct p9_client *clnt); +-struct p9_fid *p9_client_xattrwalk(struct p9_fid *, const char *, u64 *); +-int p9_client_xattrcreate(struct p9_fid *, const char *, u64, int); ++struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid, ++ const char *attr_name, u64 *attr_size); ++int p9_client_xattrcreate(struct p9_fid *fid, const char *name, ++ u64 attr_size, int flags); + int p9_client_readlink(struct p9_fid *fid, char **target); + + int p9_client_init(void); +diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h +index 3eb4261b29588..7215976116257 100644 +--- a/include/net/9p/transport.h ++++ b/include/net/9p/transport.h +@@ -40,14 +40,16 @@ struct p9_trans_module { + int maxsize; /* max message size of transport */ + int def; /* this transport should be default */ + struct module *owner; +- int (*create)(struct p9_client *, const char *, char *); +- void (*close) (struct p9_client *); +- int (*request) (struct p9_client *, struct p9_req_t *req); +- int (*cancel) (struct p9_client *, struct p9_req_t *req); +- int (*cancelled)(struct p9_client *, struct p9_req_t *req); +- int (*zc_request)(struct p9_client *, struct p9_req_t *, +- struct iov_iter *, struct iov_iter *, int , int, int); +- int (*show_options)(struct seq_file *, struct p9_client *); ++ int (*create)(struct p9_client *client, ++ const char *devname, char *args); ++ void (*close)(struct p9_client *client); ++ int (*request)(struct p9_client *client, struct p9_req_t *req); ++ int (*cancel)(struct p9_client *client, struct p9_req_t *req); ++ int (*cancelled)(struct p9_client *client, struct p9_req_t *req); ++ int (*zc_request)(struct p9_client *client, struct p9_req_t *req, ++ struct iov_iter *uidata, struct iov_iter *uodata, ++ int inlen, int outlen, int in_hdr_len); ++ int (*show_options)(struct seq_file *m, struct p9_client *client); + }; + + void v9fs_register_trans(struct p9_trans_module *m); +diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h +index 81b9659530368..56f1286583d3c 100644 +--- a/include/net/inet6_hashtables.h ++++ b/include/net/inet6_hashtables.h +@@ -103,15 +103,24 @@ struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, + const int dif); + + int inet6_hash(struct sock *sk); +-#endif /* IS_ENABLED(CONFIG_IPV6) */ + +-#define INET6_MATCH(__sk, __net, __saddr, __daddr, __ports, __dif, __sdif) \ +- (((__sk)->sk_portpair == (__ports)) && \ +- ((__sk)->sk_family == AF_INET6) && \ +- ipv6_addr_equal(&(__sk)->sk_v6_daddr, (__saddr)) && \ +- ipv6_addr_equal(&(__sk)->sk_v6_rcv_saddr, (__daddr)) && \ +- (((__sk)->sk_bound_dev_if == (__dif)) || \ +- ((__sk)->sk_bound_dev_if == (__sdif))) && \ +- net_eq(sock_net(__sk), (__net))) ++static inline bool inet6_match(struct net *net, const struct sock *sk, ++ const struct in6_addr *saddr, ++ const struct in6_addr *daddr, ++ const __portpair ports, ++ const int dif, const int sdif) ++{ ++ if (!net_eq(sock_net(sk), net) || ++ sk->sk_family != AF_INET6 || ++ sk->sk_portpair != ports || ++ !ipv6_addr_equal(&sk->sk_v6_daddr, saddr) || ++ !ipv6_addr_equal(&sk->sk_v6_rcv_saddr, daddr)) ++ return false; ++ ++ /* READ_ONCE() paired with WRITE_ONCE() in sock_bindtoindex_locked() */ ++ return inet_sk_bound_dev_eq(net, READ_ONCE(sk->sk_bound_dev_if), dif, ++ sdif); ++} ++#endif /* IS_ENABLED(CONFIG_IPV6) */ + + #endif /* _INET6_HASHTABLES_H */ +diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h +index 749bb1e460871..53c22b64e9724 100644 +--- a/include/net/inet_hashtables.h ++++ b/include/net/inet_hashtables.h +@@ -203,17 +203,6 @@ static inline void inet_ehash_locks_free(struct inet_hashinfo *hashinfo) + hashinfo->ehash_locks = NULL; + } + +-static inline bool inet_sk_bound_dev_eq(struct net *net, int bound_dev_if, +- int dif, int sdif) +-{ +-#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV) +- return inet_bound_dev_eq(!!READ_ONCE(net->ipv4.sysctl_tcp_l3mdev_accept), +- bound_dev_if, dif, sdif); +-#else +- return inet_bound_dev_eq(true, bound_dev_if, dif, sdif); +-#endif +-} +- + struct inet_bind_bucket * + inet_bind_bucket_create(struct kmem_cache *cachep, struct net *net, + struct inet_bind_hashbucket *head, +@@ -295,7 +284,6 @@ static inline struct sock *inet_lookup_listener(struct net *net, + ((__force __portpair)(((__u32)(__dport) << 16) | (__force __u32)(__be16)(__sport))) + #endif + +-#if (BITS_PER_LONG == 64) + #ifdef __BIG_ENDIAN + #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ + const __addrpair __name = (__force __addrpair) ( \ +@@ -307,24 +295,20 @@ static inline struct sock *inet_lookup_listener(struct net *net, + (((__force __u64)(__be32)(__daddr)) << 32) | \ + ((__force __u64)(__be32)(__saddr))) + #endif /* __BIG_ENDIAN */ +-#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif, __sdif) \ +- (((__sk)->sk_portpair == (__ports)) && \ +- ((__sk)->sk_addrpair == (__cookie)) && \ +- (((__sk)->sk_bound_dev_if == (__dif)) || \ +- ((__sk)->sk_bound_dev_if == (__sdif))) && \ +- net_eq(sock_net(__sk), (__net))) +-#else /* 32-bit arch */ +-#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ +- const int __name __deprecated __attribute__((unused)) +- +-#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif, __sdif) \ +- (((__sk)->sk_portpair == (__ports)) && \ +- ((__sk)->sk_daddr == (__saddr)) && \ +- ((__sk)->sk_rcv_saddr == (__daddr)) && \ +- (((__sk)->sk_bound_dev_if == (__dif)) || \ +- ((__sk)->sk_bound_dev_if == (__sdif))) && \ +- net_eq(sock_net(__sk), (__net))) +-#endif /* 64-bit arch */ ++ ++static inline bool INET_MATCH(struct net *net, const struct sock *sk, ++ const __addrpair cookie, const __portpair ports, ++ int dif, int sdif) ++{ ++ if (!net_eq(sock_net(sk), net) || ++ sk->sk_portpair != ports || ++ sk->sk_addrpair != cookie) ++ return false; ++ ++ /* READ_ONCE() paired with WRITE_ONCE() in sock_bindtoindex_locked() */ ++ return inet_sk_bound_dev_eq(net, READ_ONCE(sk->sk_bound_dev_if), dif, ++ sdif); ++} + + /* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so we need + * not check it for lookups anymore, thanks Alexey. -DaveM +diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h +index c307a547d2cb4..2c2b41ea7f81d 100644 +--- a/include/net/inet_sock.h ++++ b/include/net/inet_sock.h +@@ -149,6 +149,17 @@ static inline bool inet_bound_dev_eq(bool l3mdev_accept, int bound_dev_if, + return bound_dev_if == dif || bound_dev_if == sdif; + } + ++static inline bool inet_sk_bound_dev_eq(struct net *net, int bound_dev_if, ++ int dif, int sdif) ++{ ++#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV) ++ return inet_bound_dev_eq(!!READ_ONCE(net->ipv4.sysctl_tcp_l3mdev_accept), ++ bound_dev_if, dif, sdif); ++#else ++ return inet_bound_dev_eq(true, bound_dev_if, dif, sdif); ++#endif ++} ++ + struct inet_cork { + unsigned int flags; + __be32 addr; +diff --git a/include/net/sock.h b/include/net/sock.h +index 819c53965ef35..49a6315d521ff 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -161,9 +161,6 @@ typedef __u64 __bitwise __addrpair; + * for struct sock and struct inet_timewait_sock. + */ + struct sock_common { +- /* skc_daddr and skc_rcv_saddr must be grouped on a 8 bytes aligned +- * address on 64bit arches : cf INET_MATCH() +- */ + union { + __addrpair skc_addrpair; + struct { +@@ -1507,19 +1504,23 @@ static inline bool sk_has_account(struct sock *sk) + + static inline bool sk_wmem_schedule(struct sock *sk, int size) + { ++ int delta; ++ + if (!sk_has_account(sk)) + return true; +- return size <= sk->sk_forward_alloc || +- __sk_mem_schedule(sk, size, SK_MEM_SEND); ++ delta = size - sk->sk_forward_alloc; ++ return delta <= 0 || __sk_mem_schedule(sk, delta, SK_MEM_SEND); + } + + static inline bool + sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, int size) + { ++ int delta; ++ + if (!sk_has_account(sk)) + return true; +- return size <= sk->sk_forward_alloc || +- __sk_mem_schedule(sk, size, SK_MEM_RECV) || ++ delta = size - sk->sk_forward_alloc; ++ return delta <= 0 || __sk_mem_schedule(sk, delta, SK_MEM_RECV) || + skb_pfmemalloc(skb); + } + +diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h +index 6ad01d7de4809..a071f6ffd7fa8 100644 +--- a/include/scsi/libiscsi.h ++++ b/include/scsi/libiscsi.h +@@ -400,7 +400,7 @@ extern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev); + extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, + int dd_data_size, + bool xmit_can_sleep); +-extern void iscsi_host_remove(struct Scsi_Host *shost); ++extern void iscsi_host_remove(struct Scsi_Host *shost, bool is_shutdown); + extern void iscsi_host_free(struct Scsi_Host *shost); + extern int iscsi_target_alloc(struct scsi_target *starget); + extern int iscsi_host_get_max_scsi_cmds(struct Scsi_Host *shost, +diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h +index 3ecf9702287be..0f2f149ad916c 100644 +--- a/include/scsi/scsi_transport_iscsi.h ++++ b/include/scsi/scsi_transport_iscsi.h +@@ -441,6 +441,7 @@ extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost, + struct iscsi_transport *t, + int dd_size, + unsigned int target_id); ++extern void iscsi_force_destroy_session(struct iscsi_cls_session *session); + extern void iscsi_remove_session(struct iscsi_cls_session *session); + extern void iscsi_free_session(struct iscsi_cls_session *session); + extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess, +diff --git a/include/trace/bpf_probe.h b/include/trace/bpf_probe.h +index a23be89119aa5..04939b2d2f192 100644 +--- a/include/trace/bpf_probe.h ++++ b/include/trace/bpf_probe.h +@@ -21,6 +21,22 @@ + #undef __get_bitmask + #define __get_bitmask(field) (char *)__get_dynamic_array(field) + ++#undef __get_rel_dynamic_array ++#define __get_rel_dynamic_array(field) \ ++ ((void *)(&__entry->__rel_loc_##field) + \ ++ sizeof(__entry->__rel_loc_##field) + \ ++ (__entry->__rel_loc_##field & 0xffff)) ++ ++#undef __get_rel_dynamic_array_len ++#define __get_rel_dynamic_array_len(field) \ ++ ((__entry->__rel_loc_##field >> 16) & 0xffff) ++ ++#undef __get_rel_str ++#define __get_rel_str(field) ((char *)__get_rel_dynamic_array(field)) ++ ++#undef __get_rel_bitmask ++#define __get_rel_bitmask(field) (char *)__get_rel_dynamic_array(field) ++ + #undef __perf_count + #define __perf_count(c) (c) + +diff --git a/include/trace/events/spmi.h b/include/trace/events/spmi.h +index 8b60efe18ba68..a6819fd85cdf4 100644 +--- a/include/trace/events/spmi.h ++++ b/include/trace/events/spmi.h +@@ -21,15 +21,15 @@ TRACE_EVENT(spmi_write_begin, + __field ( u8, sid ) + __field ( u16, addr ) + __field ( u8, len ) +- __dynamic_array ( u8, buf, len + 1 ) ++ __dynamic_array ( u8, buf, len ) + ), + + TP_fast_assign( + __entry->opcode = opcode; + __entry->sid = sid; + __entry->addr = addr; +- __entry->len = len + 1; +- memcpy(__get_dynamic_array(buf), buf, len + 1); ++ __entry->len = len; ++ memcpy(__get_dynamic_array(buf), buf, len); + ), + + TP_printk("opc=%d sid=%02d addr=0x%04x len=%d buf=0x[%*phD]", +@@ -92,7 +92,7 @@ TRACE_EVENT(spmi_read_end, + __field ( u16, addr ) + __field ( int, ret ) + __field ( u8, len ) +- __dynamic_array ( u8, buf, len + 1 ) ++ __dynamic_array ( u8, buf, len ) + ), + + TP_fast_assign( +@@ -100,8 +100,8 @@ TRACE_EVENT(spmi_read_end, + __entry->sid = sid; + __entry->addr = addr; + __entry->ret = ret; +- __entry->len = len + 1; +- memcpy(__get_dynamic_array(buf), buf, len + 1); ++ __entry->len = len; ++ memcpy(__get_dynamic_array(buf), buf, len); + ), + + TP_printk("opc=%d sid=%02d addr=0x%04x ret=%d len=%02d buf=0x[%*phD]", +diff --git a/include/trace/perf.h b/include/trace/perf.h +index dbc6c74defc38..5d48c46a30083 100644 +--- a/include/trace/perf.h ++++ b/include/trace/perf.h +@@ -21,6 +21,23 @@ + #undef __get_bitmask + #define __get_bitmask(field) (char *)__get_dynamic_array(field) + ++#undef __get_rel_dynamic_array ++#define __get_rel_dynamic_array(field) \ ++ ((void *)__entry + \ ++ offsetof(typeof(*__entry), __rel_loc_##field) + \ ++ sizeof(__entry->__rel_loc_##field) + \ ++ (__entry->__rel_loc_##field & 0xffff)) ++ ++#undef __get_rel_dynamic_array_len ++#define __get_rel_dynamic_array_len(field) \ ++ ((__entry->__rel_loc_##field >> 16) & 0xffff) ++ ++#undef __get_rel_str ++#define __get_rel_str(field) ((char *)__get_rel_dynamic_array(field)) ++ ++#undef __get_rel_bitmask ++#define __get_rel_bitmask(field) (char *)__get_rel_dynamic_array(field) ++ + #undef __perf_count + #define __perf_count(c) (__count = (c)) + +diff --git a/include/trace/trace_events.h b/include/trace/trace_events.h +index 08810a4638805..a77b690709cc1 100644 +--- a/include/trace/trace_events.h ++++ b/include/trace/trace_events.h +@@ -108,6 +108,18 @@ TRACE_MAKE_SYSTEM_STR(); + #undef __bitmask + #define __bitmask(item, nr_bits) __dynamic_array(char, item, -1) + ++#undef __rel_dynamic_array ++#define __rel_dynamic_array(type, item, len) u32 __rel_loc_##item; ++ ++#undef __rel_string ++#define __rel_string(item, src) __rel_dynamic_array(char, item, -1) ++ ++#undef __rel_string_len ++#define __rel_string_len(item, src, len) __rel_dynamic_array(char, item, -1) ++ ++#undef __rel_bitmask ++#define __rel_bitmask(item, nr_bits) __rel_dynamic_array(char, item, -1) ++ + #undef TP_STRUCT__entry + #define TP_STRUCT__entry(args...) args + +@@ -116,7 +128,7 @@ TRACE_MAKE_SYSTEM_STR(); + struct trace_event_raw_##name { \ + struct trace_entry ent; \ + tstruct \ +- char __data[0]; \ ++ char __data[]; \ + }; \ + \ + static struct trace_event_class event_class_##name; +@@ -200,11 +212,23 @@ TRACE_MAKE_SYSTEM_STR(); + #undef __string + #define __string(item, src) __dynamic_array(char, item, -1) + ++#undef __bitmask ++#define __bitmask(item, nr_bits) __dynamic_array(unsigned long, item, -1) ++ + #undef __string_len + #define __string_len(item, src, len) __dynamic_array(char, item, -1) + +-#undef __bitmask +-#define __bitmask(item, nr_bits) __dynamic_array(unsigned long, item, -1) ++#undef __rel_dynamic_array ++#define __rel_dynamic_array(type, item, len) u32 item; ++ ++#undef __rel_string ++#define __rel_string(item, src) __rel_dynamic_array(char, item, -1) ++ ++#undef __rel_string_len ++#define __rel_string_len(item, src, len) __rel_dynamic_array(char, item, -1) ++ ++#undef __rel_bitmask ++#define __rel_bitmask(item, nr_bits) __rel_dynamic_array(unsigned long, item, -1) + + #undef DECLARE_EVENT_CLASS + #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ +@@ -293,6 +317,20 @@ TRACE_MAKE_SYSTEM_STR(); + #undef __get_str + #define __get_str(field) ((char *)__get_dynamic_array(field)) + ++#undef __get_rel_dynamic_array ++#define __get_rel_dynamic_array(field) \ ++ ((void *)__entry + \ ++ offsetof(typeof(*__entry), __rel_loc_##field) + \ ++ sizeof(__entry->__rel_loc_##field) + \ ++ (__entry->__rel_loc_##field & 0xffff)) ++ ++#undef __get_rel_dynamic_array_len ++#define __get_rel_dynamic_array_len(field) \ ++ ((__entry->__rel_loc_##field >> 16) & 0xffff) ++ ++#undef __get_rel_str ++#define __get_rel_str(field) ((char *)__get_rel_dynamic_array(field)) ++ + #undef __get_bitmask + #define __get_bitmask(field) \ + ({ \ +@@ -302,6 +340,15 @@ TRACE_MAKE_SYSTEM_STR(); + trace_print_bitmask_seq(p, __bitmask, __bitmask_size); \ + }) + ++#undef __get_rel_bitmask ++#define __get_rel_bitmask(field) \ ++ ({ \ ++ void *__bitmask = __get_rel_dynamic_array(field); \ ++ unsigned int __bitmask_size; \ ++ __bitmask_size = __get_rel_dynamic_array_len(field); \ ++ trace_print_bitmask_seq(p, __bitmask, __bitmask_size); \ ++ }) ++ + #undef __print_flags + #define __print_flags(flag, delim, flag_array...) \ + ({ \ +@@ -432,16 +479,18 @@ static struct trace_event_functions trace_event_type_funcs_##call = { \ + + #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) + ++#define ALIGN_STRUCTFIELD(type) ((int)(offsetof(struct {char a; type b;}, b))) ++ + #undef __field_ext + #define __field_ext(_type, _item, _filter_type) { \ + .type = #_type, .name = #_item, \ +- .size = sizeof(_type), .align = __alignof__(_type), \ ++ .size = sizeof(_type), .align = ALIGN_STRUCTFIELD(_type), \ + .is_signed = is_signed_type(_type), .filter_type = _filter_type }, + + #undef __field_struct_ext + #define __field_struct_ext(_type, _item, _filter_type) { \ + .type = #_type, .name = #_item, \ +- .size = sizeof(_type), .align = __alignof__(_type), \ ++ .size = sizeof(_type), .align = ALIGN_STRUCTFIELD(_type), \ + 0, .filter_type = _filter_type }, + + #undef __field +@@ -453,7 +502,7 @@ static struct trace_event_functions trace_event_type_funcs_##call = { \ + #undef __array + #define __array(_type, _item, _len) { \ + .type = #_type"["__stringify(_len)"]", .name = #_item, \ +- .size = sizeof(_type[_len]), .align = __alignof__(_type), \ ++ .size = sizeof(_type[_len]), .align = ALIGN_STRUCTFIELD(_type), \ + .is_signed = is_signed_type(_type), .filter_type = FILTER_OTHER }, + + #undef __dynamic_array +@@ -471,6 +520,21 @@ static struct trace_event_functions trace_event_type_funcs_##call = { \ + #undef __bitmask + #define __bitmask(item, nr_bits) __dynamic_array(unsigned long, item, -1) + ++#undef __rel_dynamic_array ++#define __rel_dynamic_array(_type, _item, _len) { \ ++ .type = "__rel_loc " #_type "[]", .name = #_item, \ ++ .size = 4, .align = 4, \ ++ .is_signed = is_signed_type(_type), .filter_type = FILTER_OTHER }, ++ ++#undef __rel_string ++#define __rel_string(item, src) __rel_dynamic_array(char, item, -1) ++ ++#undef __rel_string_len ++#define __rel_string_len(item, src, len) __rel_dynamic_array(char, item, -1) ++ ++#undef __rel_bitmask ++#define __rel_bitmask(item, nr_bits) __rel_dynamic_array(unsigned long, item, -1) ++ + #undef DECLARE_EVENT_CLASS + #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, func, print) \ + static struct trace_event_fields trace_event_fields_##call[] = { \ +@@ -519,6 +583,22 @@ static struct trace_event_fields trace_event_fields_##call[] = { \ + #undef __string_len + #define __string_len(item, src, len) __dynamic_array(char, item, (len) + 1) + ++#undef __rel_dynamic_array ++#define __rel_dynamic_array(type, item, len) \ ++ __item_length = (len) * sizeof(type); \ ++ __data_offsets->item = __data_size + \ ++ offsetof(typeof(*entry), __data) - \ ++ offsetof(typeof(*entry), __rel_loc_##item) - \ ++ sizeof(u32); \ ++ __data_offsets->item |= __item_length << 16; \ ++ __data_size += __item_length; ++ ++#undef __rel_string ++#define __rel_string(item, src) __rel_dynamic_array(char, item, \ ++ strlen((src) ? (const char *)(src) : "(null)") + 1) ++ ++#undef __rel_string_len ++#define __rel_string_len(item, src, len) __rel_dynamic_array(char, item, (len) + 1) + /* + * __bitmask_size_in_bytes_raw is the number of bytes needed to hold + * num_possible_cpus(). +@@ -542,6 +622,10 @@ static struct trace_event_fields trace_event_fields_##call[] = { \ + #define __bitmask(item, nr_bits) __dynamic_array(unsigned long, item, \ + __bitmask_size_in_longs(nr_bits)) + ++#undef __rel_bitmask ++#define __rel_bitmask(item, nr_bits) __rel_dynamic_array(unsigned long, item, \ ++ __bitmask_size_in_longs(nr_bits)) ++ + #undef DECLARE_EVENT_CLASS + #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ + static inline notrace int trace_event_get_offsets_##call( \ +@@ -706,6 +790,37 @@ static inline notrace int trace_event_get_offsets_##call( \ + #define __assign_bitmask(dst, src, nr_bits) \ + memcpy(__get_bitmask(dst), (src), __bitmask_size_in_bytes(nr_bits)) + ++#undef __rel_dynamic_array ++#define __rel_dynamic_array(type, item, len) \ ++ __entry->__rel_loc_##item = __data_offsets.item; ++ ++#undef __rel_string ++#define __rel_string(item, src) __rel_dynamic_array(char, item, -1) ++ ++#undef __rel_string_len ++#define __rel_string_len(item, src, len) __rel_dynamic_array(char, item, -1) ++ ++#undef __assign_rel_str ++#define __assign_rel_str(dst, src) \ ++ strcpy(__get_rel_str(dst), (src) ? (const char *)(src) : "(null)"); ++ ++#undef __assign_rel_str_len ++#define __assign_rel_str_len(dst, src, len) \ ++ do { \ ++ memcpy(__get_rel_str(dst), (src), (len)); \ ++ __get_rel_str(dst)[len] = '\0'; \ ++ } while (0) ++ ++#undef __rel_bitmask ++#define __rel_bitmask(item, nr_bits) __rel_dynamic_array(unsigned long, item, -1) ++ ++#undef __get_rel_bitmask ++#define __get_rel_bitmask(field) (char *)__get_rel_dynamic_array(field) ++ ++#undef __assign_rel_bitmask ++#define __assign_rel_bitmask(dst, src, nr_bits) \ ++ memcpy(__get_rel_bitmask(dst), (src), __bitmask_size_in_bytes(nr_bits)) ++ + #undef TP_fast_assign + #define TP_fast_assign(args...) args + +@@ -770,6 +885,10 @@ static inline void ftrace_test_probe_##call(void) \ + #undef __get_dynamic_array_len + #undef __get_str + #undef __get_bitmask ++#undef __get_rel_dynamic_array ++#undef __get_rel_dynamic_array_len ++#undef __get_rel_str ++#undef __get_rel_bitmask + #undef __print_array + #undef __print_hex_dump + +diff --git a/include/uapi/linux/can/error.h b/include/uapi/linux/can/error.h +index 34633283de641..a1000cb630632 100644 +--- a/include/uapi/linux/can/error.h ++++ b/include/uapi/linux/can/error.h +@@ -120,6 +120,9 @@ + #define CAN_ERR_TRX_CANL_SHORT_TO_GND 0x70 /* 0111 0000 */ + #define CAN_ERR_TRX_CANL_SHORT_TO_CANH 0x80 /* 1000 0000 */ + +-/* controller specific additional information / data[5..7] */ ++/* data[5] is reserved (do not use) */ ++ ++/* TX error counter / data[6] */ ++/* RX error counter / data[7] */ + + #endif /* _UAPI_CAN_ERROR_H */ +diff --git a/include/uapi/linux/netfilter/xt_IDLETIMER.h b/include/uapi/linux/netfilter/xt_IDLETIMER.h +index 49ddcdc61c094..7bfb31a66fc9b 100644 +--- a/include/uapi/linux/netfilter/xt_IDLETIMER.h ++++ b/include/uapi/linux/netfilter/xt_IDLETIMER.h +@@ -1,6 +1,5 @@ ++/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ + /* +- * linux/include/linux/netfilter/xt_IDLETIMER.h +- * + * Header file for Xtables timer target module. + * + * Copyright (C) 2004, 2010 Nokia Corporation +@@ -10,20 +9,6 @@ + * by Luciano Coelho <luciano.coelho@nokia.com> + * + * Contact: Luciano Coelho <luciano.coelho@nokia.com> +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * version 2 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, but +- * WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- * General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +- * 02110-1301 USA + */ + + #ifndef _XT_IDLETIMER_H +diff --git a/init/main.c b/init/main.c +index cf79b5a766cb1..649d9e4201a80 100644 +--- a/init/main.c ++++ b/init/main.c +@@ -100,6 +100,7 @@ + #include <linux/kcsan.h> + #include <linux/init_syscalls.h> + #include <linux/stackdepot.h> ++#include <linux/randomize_kstack.h> + #include <net/net_namespace.h> + + #include <asm/io.h> +diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c +index fe053ffd89329..565e4c59db660 100644 +--- a/kernel/bpf/cgroup.c ++++ b/kernel/bpf/cgroup.c +@@ -667,6 +667,60 @@ static struct bpf_prog_list *find_detach_entry(struct list_head *progs, + return ERR_PTR(-ENOENT); + } + ++/** ++ * purge_effective_progs() - After compute_effective_progs fails to alloc new ++ * cgrp->bpf.inactive table we can recover by ++ * recomputing the array in place. ++ * ++ * @cgrp: The cgroup which descendants to travers ++ * @prog: A program to detach or NULL ++ * @link: A link to detach or NULL ++ * @atype: Type of detach operation ++ */ ++static void purge_effective_progs(struct cgroup *cgrp, struct bpf_prog *prog, ++ struct bpf_cgroup_link *link, ++ enum cgroup_bpf_attach_type atype) ++{ ++ struct cgroup_subsys_state *css; ++ struct bpf_prog_array *progs; ++ struct bpf_prog_list *pl; ++ struct list_head *head; ++ struct cgroup *cg; ++ int pos; ++ ++ /* recompute effective prog array in place */ ++ css_for_each_descendant_pre(css, &cgrp->self) { ++ struct cgroup *desc = container_of(css, struct cgroup, self); ++ ++ if (percpu_ref_is_zero(&desc->bpf.refcnt)) ++ continue; ++ ++ /* find position of link or prog in effective progs array */ ++ for (pos = 0, cg = desc; cg; cg = cgroup_parent(cg)) { ++ if (pos && !(cg->bpf.flags[atype] & BPF_F_ALLOW_MULTI)) ++ continue; ++ ++ head = &cg->bpf.progs[atype]; ++ list_for_each_entry(pl, head, node) { ++ if (!prog_list_prog(pl)) ++ continue; ++ if (pl->prog == prog && pl->link == link) ++ goto found; ++ pos++; ++ } ++ } ++found: ++ BUG_ON(!cg); ++ progs = rcu_dereference_protected( ++ desc->bpf.effective[atype], ++ lockdep_is_held(&cgroup_mutex)); ++ ++ /* Remove the program from the array */ ++ WARN_ONCE(bpf_prog_array_delete_safe_at(progs, pos), ++ "Failed to purge a prog from array at index %d", pos); ++ } ++} ++ + /** + * __cgroup_bpf_detach() - Detach the program or link from a cgroup, and + * propagate the change to descendants +@@ -686,7 +740,6 @@ int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, + struct bpf_prog_list *pl; + struct list_head *progs; + u32 flags; +- int err; + + atype = to_cgroup_bpf_attach_type(type); + if (atype < 0) +@@ -708,9 +761,12 @@ int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, + pl->prog = NULL; + pl->link = NULL; + +- err = update_effective_progs(cgrp, atype); +- if (err) +- goto cleanup; ++ if (update_effective_progs(cgrp, atype)) { ++ /* if update effective array failed replace the prog with a dummy prog*/ ++ pl->prog = old_prog; ++ pl->link = link; ++ purge_effective_progs(cgrp, old_prog, link, atype); ++ } + + /* now can actually delete it from this cgroup list */ + list_del(&pl->node); +@@ -722,12 +778,6 @@ int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, + bpf_prog_put(old_prog); + static_branch_dec(&cgroup_bpf_enabled_key[atype]); + return 0; +- +-cleanup: +- /* restore back prog or link */ +- pl->prog = old_prog; +- pl->link = link; +- return err; + } + + /* Must be called with cgroup_mutex held to avoid races. */ +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 346d36c905a90..c8b534a498b38 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -12445,6 +12445,7 @@ static int jit_subprogs(struct bpf_verifier_env *env) + /* Below members will be freed only at prog->aux */ + func[i]->aux->btf = prog->aux->btf; + func[i]->aux->func_info = prog->aux->func_info; ++ func[i]->aux->func_info_cnt = prog->aux->func_info_cnt; + func[i]->aux->poke_tab = prog->aux->poke_tab; + func[i]->aux->size_poke_tab = prog->aux->size_poke_tab; + +@@ -12457,9 +12458,6 @@ static int jit_subprogs(struct bpf_verifier_env *env) + poke->aux = func[i]->aux; + } + +- /* Use bpf_prog_F_tag to indicate functions in stack traces. +- * Long term would need debug info to populate names +- */ + func[i]->aux->name[0] = 'F'; + func[i]->aux->stack_depth = env->subprog_info[i].stack_depth; + func[i]->jit_requested = 1; +diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c +index 31f94c6ea0a55..9c5b659db63f4 100644 +--- a/kernel/cgroup/cpuset.c ++++ b/kernel/cgroup/cpuset.c +@@ -2199,7 +2199,7 @@ static int cpuset_can_attach(struct cgroup_taskset *tset) + goto out_unlock; + + cgroup_taskset_for_each(task, css, tset) { +- ret = task_can_attach(task, cs->cpus_allowed); ++ ret = task_can_attach(task, cs->effective_cpus); + if (ret) + goto out_unlock; + ret = security_task_setscheduler(task); +diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c +index 2ee5419649ed7..e62fb7a4da694 100644 +--- a/kernel/dma/swiotlb.c ++++ b/kernel/dma/swiotlb.c +@@ -551,7 +551,7 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr, + int index; + phys_addr_t tlb_addr; + +- if (!mem) ++ if (!mem || !mem->nslabs) + panic("Can not allocate SWIOTLB buffer earlier and can't now provide you with the DMA bounce buffer"); + + if (mem_encrypt_active()) +diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig +index fbc54c2a7f239..00d58588ea95a 100644 +--- a/kernel/irq/Kconfig ++++ b/kernel/irq/Kconfig +@@ -82,6 +82,7 @@ config IRQ_FASTEOI_HIERARCHY_HANDLERS + # Generic IRQ IPI support + config GENERIC_IRQ_IPI + bool ++ depends on SMP + select IRQ_DOMAIN_HIERARCHY + + # Generic MSI interrupt support +diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c +index a98bcfc4be7bc..f3920374f71ce 100644 +--- a/kernel/irq/chip.c ++++ b/kernel/irq/chip.c +@@ -1516,7 +1516,8 @@ int irq_chip_request_resources_parent(struct irq_data *data) + if (data->chip->irq_request_resources) + return data->chip->irq_request_resources(data); + +- return -ENOSYS; ++ /* no error on missing optional irq_chip::irq_request_resources */ ++ return 0; + } + EXPORT_SYMBOL_GPL(irq_chip_request_resources_parent); + +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 4d8fc65cf38f4..035e3038c4de4 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -910,6 +910,8 @@ struct irq_desc *__irq_resolve_mapping(struct irq_domain *domain, + data = irq_domain_get_irq_data(domain, hwirq); + if (data && data->hwirq == hwirq) + desc = irq_data_to_desc(data); ++ if (irq && desc) ++ *irq = hwirq; + } + + return desc; +diff --git a/kernel/kprobes.c b/kernel/kprobes.c +index 2ef90d15699fb..3a3c0166bd1f3 100644 +--- a/kernel/kprobes.c ++++ b/kernel/kprobes.c +@@ -1559,7 +1559,8 @@ static int check_kprobe_address_safe(struct kprobe *p, + preempt_disable(); + + /* Ensure it is not in reserved area nor out of text */ +- if (!kernel_text_address((unsigned long) p->addr) || ++ if (!(core_kernel_text((unsigned long) p->addr) || ++ is_module_text_address((unsigned long) p->addr)) || + within_kprobe_blacklist((unsigned long) p->addr) || + jump_label_text_reserved(p->addr, p->addr) || + static_call_text_reserved(p->addr, p->addr) || +diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c +index a30702b847ba8..120bbdacd58bb 100644 +--- a/kernel/locking/lockdep.c ++++ b/kernel/locking/lockdep.c +@@ -5202,9 +5202,10 @@ __lock_set_class(struct lockdep_map *lock, const char *name, + return 0; + } + +- lockdep_init_map_waits(lock, name, key, 0, +- lock->wait_type_inner, +- lock->wait_type_outer); ++ lockdep_init_map_type(lock, name, key, 0, ++ lock->wait_type_inner, ++ lock->wait_type_outer, ++ lock->lock_type); + class = register_lock_class(lock, subclass, 0); + hlock->class_idx = class - lock_classes; + +diff --git a/kernel/power/user.c b/kernel/power/user.c +index 740723bb38852..13cca2e2c2bc6 100644 +--- a/kernel/power/user.c ++++ b/kernel/power/user.c +@@ -26,6 +26,7 @@ + + #include "power.h" + ++static bool need_wait; + + static struct snapshot_data { + struct snapshot_handle handle; +@@ -78,7 +79,7 @@ static int snapshot_open(struct inode *inode, struct file *filp) + * Resuming. We may need to wait for the image device to + * appear. + */ +- wait_for_device_probe(); ++ need_wait = true; + + data->swap = -1; + data->mode = O_WRONLY; +@@ -168,6 +169,11 @@ static ssize_t snapshot_write(struct file *filp, const char __user *buf, + ssize_t res; + loff_t pg_offp = *offp & ~PAGE_MASK; + ++ if (need_wait) { ++ wait_for_device_probe(); ++ need_wait = false; ++ } ++ + lock_system_sleep(); + + data = filp->private_data; +@@ -244,6 +250,11 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, + loff_t size; + sector_t offset; + ++ if (need_wait) { ++ wait_for_device_probe(); ++ need_wait = false; ++ } ++ + if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC) + return -ENOTTY; + if (_IOC_NR(cmd) > SNAPSHOT_IOC_MAXNR) +diff --git a/kernel/profile.c b/kernel/profile.c +index eb9c7f0f5ac52..0db1122855c0d 100644 +--- a/kernel/profile.c ++++ b/kernel/profile.c +@@ -109,6 +109,13 @@ int __ref profile_init(void) + + /* only text is profiled */ + prof_len = (_etext - _stext) >> prof_shift; ++ ++ if (!prof_len) { ++ pr_warn("profiling shift: %u too large\n", prof_shift); ++ prof_on = 0; ++ return -EINVAL; ++ } ++ + buffer_bytes = prof_len*sizeof(atomic_t); + + if (!alloc_cpumask_var(&prof_cpu_mask, GFP_KERNEL)) +diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c +index f922937eb39ad..d820ef615475b 100644 +--- a/kernel/rcu/rcutorture.c ++++ b/kernel/rcu/rcutorture.c +@@ -1991,6 +1991,19 @@ static int rcutorture_booster_init(unsigned int cpu) + if (boost_tasks[cpu] != NULL) + return 0; /* Already created, nothing more to do. */ + ++ // Testing RCU priority boosting requires rcutorture do ++ // some serious abuse. Counter this by running ksoftirqd ++ // at higher priority. ++ if (IS_BUILTIN(CONFIG_RCU_TORTURE_TEST)) { ++ struct sched_param sp; ++ struct task_struct *t; ++ ++ t = per_cpu(ksoftirqd, cpu); ++ WARN_ON_ONCE(!t); ++ sp.sched_priority = 2; ++ sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); ++ } ++ + /* Don't allow time recalculation while creating a new task. */ + mutex_lock(&boost_mutex); + rcu_torture_disable_rt_throttle(); +@@ -2848,7 +2861,7 @@ rcu_torture_cleanup(void) + rcutorture_seq_diff(gp_seq, start_gp_seq)); + torture_stop_kthread(rcu_torture_stats, stats_task); + torture_stop_kthread(rcu_torture_fqs, fqs_task); +- if (rcu_torture_can_boost()) ++ if (rcu_torture_can_boost() && rcutor_hp >= 0) + cpuhp_remove_state(rcutor_hp); + + /* +@@ -3066,7 +3079,7 @@ rcu_torture_init(void) + rcu_torture_write_types(); + firsterr = torture_create_kthread(rcu_torture_writer, NULL, + writer_task); +- if (firsterr) ++ if (torture_init_error(firsterr)) + goto unwind; + if (nfakewriters > 0) { + fakewriter_tasks = kcalloc(nfakewriters, +@@ -3081,7 +3094,7 @@ rcu_torture_init(void) + for (i = 0; i < nfakewriters; i++) { + firsterr = torture_create_kthread(rcu_torture_fakewriter, + NULL, fakewriter_tasks[i]); +- if (firsterr) ++ if (torture_init_error(firsterr)) + goto unwind; + } + reader_tasks = kcalloc(nrealreaders, sizeof(reader_tasks[0]), +@@ -3097,7 +3110,7 @@ rcu_torture_init(void) + rcu_torture_reader_mbchk[i].rtc_chkrdr = -1; + firsterr = torture_create_kthread(rcu_torture_reader, (void *)i, + reader_tasks[i]); +- if (firsterr) ++ if (torture_init_error(firsterr)) + goto unwind; + } + nrealnocbers = nocbs_nthreads; +@@ -3117,18 +3130,18 @@ rcu_torture_init(void) + } + for (i = 0; i < nrealnocbers; i++) { + firsterr = torture_create_kthread(rcu_nocb_toggle, NULL, nocb_tasks[i]); +- if (firsterr) ++ if (torture_init_error(firsterr)) + goto unwind; + } + if (stat_interval > 0) { + firsterr = torture_create_kthread(rcu_torture_stats, NULL, + stats_task); +- if (firsterr) ++ if (torture_init_error(firsterr)) + goto unwind; + } + if (test_no_idle_hz && shuffle_interval > 0) { + firsterr = torture_shuffle_init(shuffle_interval * HZ); +- if (firsterr) ++ if (torture_init_error(firsterr)) + goto unwind; + } + if (stutter < 0) +@@ -3138,7 +3151,7 @@ rcu_torture_init(void) + + t = cur_ops->stall_dur ? cur_ops->stall_dur() : stutter * HZ; + firsterr = torture_stutter_init(stutter * HZ, t); +- if (firsterr) ++ if (torture_init_error(firsterr)) + goto unwind; + } + if (fqs_duration < 0) +@@ -3147,7 +3160,7 @@ rcu_torture_init(void) + /* Create the fqs thread */ + firsterr = torture_create_kthread(rcu_torture_fqs, NULL, + fqs_task); +- if (firsterr) ++ if (torture_init_error(firsterr)) + goto unwind; + } + if (test_boost_interval < 1) +@@ -3161,44 +3174,29 @@ rcu_torture_init(void) + firsterr = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "RCU_TORTURE", + rcutorture_booster_init, + rcutorture_booster_cleanup); +- if (firsterr < 0) +- goto unwind; + rcutor_hp = firsterr; +- +- // Testing RCU priority boosting requires rcutorture do +- // some serious abuse. Counter this by running ksoftirqd +- // at higher priority. +- if (IS_BUILTIN(CONFIG_RCU_TORTURE_TEST)) { +- for_each_online_cpu(cpu) { +- struct sched_param sp; +- struct task_struct *t; +- +- t = per_cpu(ksoftirqd, cpu); +- WARN_ON_ONCE(!t); +- sp.sched_priority = 2; +- sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); +- } +- } ++ if (torture_init_error(firsterr)) ++ goto unwind; + } + shutdown_jiffies = jiffies + shutdown_secs * HZ; + firsterr = torture_shutdown_init(shutdown_secs, rcu_torture_cleanup); +- if (firsterr) ++ if (torture_init_error(firsterr)) + goto unwind; + firsterr = torture_onoff_init(onoff_holdoff * HZ, onoff_interval, + rcutorture_sync); +- if (firsterr) ++ if (torture_init_error(firsterr)) + goto unwind; + firsterr = rcu_torture_stall_init(); +- if (firsterr) ++ if (torture_init_error(firsterr)) + goto unwind; + firsterr = rcu_torture_fwd_prog_init(); +- if (firsterr) ++ if (torture_init_error(firsterr)) + goto unwind; + firsterr = rcu_torture_barrier_init(); +- if (firsterr) ++ if (torture_init_error(firsterr)) + goto unwind; + firsterr = rcu_torture_read_exit_init(); +- if (firsterr) ++ if (torture_init_error(firsterr)) + goto unwind; + if (object_debug) + rcu_test_debug_objects(); +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index b89ca5c831439..85be684687b08 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -3714,7 +3714,7 @@ bool cpus_share_cache(int this_cpu, int that_cpu) + return per_cpu(sd_llc_id, this_cpu) == per_cpu(sd_llc_id, that_cpu); + } + +-static inline bool ttwu_queue_cond(int cpu, int wake_flags) ++static inline bool ttwu_queue_cond(struct task_struct *p, int cpu) + { + /* + * Do not complicate things with the async wake_list while the CPU is +@@ -3723,6 +3723,10 @@ static inline bool ttwu_queue_cond(int cpu, int wake_flags) + if (!cpu_active(cpu)) + return false; + ++ /* Ensure the task will still be allowed to run on the CPU. */ ++ if (!cpumask_test_cpu(cpu, p->cpus_ptr)) ++ return false; ++ + /* + * If the CPU does not share cache, then queue the task on the + * remote rqs wakelist to avoid accessing remote data. +@@ -3730,13 +3734,21 @@ static inline bool ttwu_queue_cond(int cpu, int wake_flags) + if (!cpus_share_cache(smp_processor_id(), cpu)) + return true; + ++ if (cpu == smp_processor_id()) ++ return false; ++ + /* +- * If the task is descheduling and the only running task on the +- * CPU then use the wakelist to offload the task activation to +- * the soon-to-be-idle CPU as the current CPU is likely busy. +- * nr_running is checked to avoid unnecessary task stacking. ++ * If the wakee cpu is idle, or the task is descheduling and the ++ * only running task on the CPU, then use the wakelist to offload ++ * the task activation to the idle (or soon-to-be-idle) CPU as ++ * the current CPU is likely busy. nr_running is checked to ++ * avoid unnecessary task stacking. ++ * ++ * Note that we can only get here with (wakee) p->on_rq=0, ++ * p->on_cpu can be whatever, we've done the dequeue, so ++ * the wakee has been accounted out of ->nr_running. + */ +- if ((wake_flags & WF_ON_CPU) && cpu_rq(cpu)->nr_running <= 1) ++ if (!cpu_rq(cpu)->nr_running) + return true; + + return false; +@@ -3744,10 +3756,7 @@ static inline bool ttwu_queue_cond(int cpu, int wake_flags) + + static bool ttwu_queue_wakelist(struct task_struct *p, int cpu, int wake_flags) + { +- if (sched_feat(TTWU_QUEUE) && ttwu_queue_cond(cpu, wake_flags)) { +- if (WARN_ON_ONCE(cpu == smp_processor_id())) +- return false; +- ++ if (sched_feat(TTWU_QUEUE) && ttwu_queue_cond(p, cpu)) { + sched_clock_cpu(cpu); /* Sync clocks across CPUs */ + __ttwu_queue_wakelist(p, cpu, wake_flags); + return true; +@@ -4069,7 +4078,7 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) + * scheduling. + */ + if (smp_load_acquire(&p->on_cpu) && +- ttwu_queue_wakelist(p, task_cpu(p), wake_flags | WF_ON_CPU)) ++ ttwu_queue_wakelist(p, task_cpu(p), wake_flags)) + goto unlock; + + /* +@@ -4585,7 +4594,8 @@ static inline void prepare_task(struct task_struct *next) + * Claim the task as running, we do this before switching to it + * such that any running task will have this set. + * +- * See the ttwu() WF_ON_CPU case and its ordering comment. ++ * See the smp_load_acquire(&p->on_cpu) case in ttwu() and ++ * its ordering comment. + */ + WRITE_ONCE(next->on_cpu, 1); + #endif +@@ -6379,8 +6389,12 @@ static inline void sched_submit_work(struct task_struct *tsk) + preempt_enable_no_resched(); + } + +- if (tsk_is_pi_blocked(tsk)) +- return; ++ /* ++ * spinlock and rwlock must not flush block requests. This will ++ * deadlock if the callback attempts to acquire a lock which is ++ * already acquired. ++ */ ++ SCHED_WARN_ON(current->__state & TASK_RTLOCK_WAIT); + + /* + * If we are going to sleep and we have plugged IO queued, +@@ -8737,7 +8751,7 @@ int cpuset_cpumask_can_shrink(const struct cpumask *cur, + } + + int task_can_attach(struct task_struct *p, +- const struct cpumask *cs_cpus_allowed) ++ const struct cpumask *cs_effective_cpus) + { + int ret = 0; + +@@ -8756,8 +8770,13 @@ int task_can_attach(struct task_struct *p, + } + + if (dl_task(p) && !cpumask_intersects(task_rq(p)->rd->span, +- cs_cpus_allowed)) +- ret = dl_task_can_attach(p, cs_cpus_allowed); ++ cs_effective_cpus)) { ++ int cpu = cpumask_any_and(cpu_active_mask, cs_effective_cpus); ++ ++ if (unlikely(cpu >= nr_cpu_ids)) ++ return -EINVAL; ++ ret = dl_cpu_busy(cpu, p); ++ } + + out: + return ret; +@@ -9041,8 +9060,10 @@ static void cpuset_cpu_active(void) + static int cpuset_cpu_inactive(unsigned int cpu) + { + if (!cpuhp_tasks_frozen) { +- if (dl_cpu_busy(cpu)) +- return -EBUSY; ++ int ret = dl_cpu_busy(cpu, NULL); ++ ++ if (ret) ++ return ret; + cpuset_update_active_cpus(); + } else { + num_cpus_frozen++; +diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c +index ee673a205e220..147b757d162b9 100644 +--- a/kernel/sched/deadline.c ++++ b/kernel/sched/deadline.c +@@ -2864,41 +2864,6 @@ bool dl_param_changed(struct task_struct *p, const struct sched_attr *attr) + } + + #ifdef CONFIG_SMP +-int dl_task_can_attach(struct task_struct *p, const struct cpumask *cs_cpus_allowed) +-{ +- unsigned long flags, cap; +- unsigned int dest_cpu; +- struct dl_bw *dl_b; +- bool overflow; +- int ret; +- +- dest_cpu = cpumask_any_and(cpu_active_mask, cs_cpus_allowed); +- +- rcu_read_lock_sched(); +- dl_b = dl_bw_of(dest_cpu); +- raw_spin_lock_irqsave(&dl_b->lock, flags); +- cap = dl_bw_capacity(dest_cpu); +- overflow = __dl_overflow(dl_b, cap, 0, p->dl.dl_bw); +- if (overflow) { +- ret = -EBUSY; +- } else { +- /* +- * We reserve space for this task in the destination +- * root_domain, as we can't fail after this point. +- * We will free resources in the source root_domain +- * later on (see set_cpus_allowed_dl()). +- */ +- int cpus = dl_bw_cpus(dest_cpu); +- +- __dl_add(dl_b, p->dl.dl_bw, cpus); +- ret = 0; +- } +- raw_spin_unlock_irqrestore(&dl_b->lock, flags); +- rcu_read_unlock_sched(); +- +- return ret; +-} +- + int dl_cpuset_cpumask_can_shrink(const struct cpumask *cur, + const struct cpumask *trial) + { +@@ -2920,7 +2885,7 @@ int dl_cpuset_cpumask_can_shrink(const struct cpumask *cur, + return ret; + } + +-bool dl_cpu_busy(unsigned int cpu) ++int dl_cpu_busy(int cpu, struct task_struct *p) + { + unsigned long flags, cap; + struct dl_bw *dl_b; +@@ -2930,11 +2895,22 @@ bool dl_cpu_busy(unsigned int cpu) + dl_b = dl_bw_of(cpu); + raw_spin_lock_irqsave(&dl_b->lock, flags); + cap = dl_bw_capacity(cpu); +- overflow = __dl_overflow(dl_b, cap, 0, 0); ++ overflow = __dl_overflow(dl_b, cap, 0, p ? p->dl.dl_bw : 0); ++ ++ if (!overflow && p) { ++ /* ++ * We reserve space for this task in the destination ++ * root_domain, as we can't fail after this point. ++ * We will free resources in the source root_domain ++ * later on (see set_cpus_allowed_dl()). ++ */ ++ __dl_add(dl_b, p->dl.dl_bw, dl_bw_cpus(cpu)); ++ } ++ + raw_spin_unlock_irqrestore(&dl_b->lock, flags); + rcu_read_unlock_sched(); + +- return overflow; ++ return overflow ? -EBUSY : 0; + } + #endif + +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index fcbacc35d2b93..a853e4e9e3c36 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -6280,6 +6280,7 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, bool + { + struct cpumask *cpus = this_cpu_cpumask_var_ptr(select_idle_mask); + int i, cpu, idle_cpu = -1, nr = INT_MAX; ++ struct sched_domain_shared *sd_share; + struct rq *this_rq = this_rq(); + int this = smp_processor_id(); + struct sched_domain *this_sd; +@@ -6319,6 +6320,17 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, bool + time = cpu_clock(this); + } + ++ if (sched_feat(SIS_UTIL)) { ++ sd_share = rcu_dereference(per_cpu(sd_llc_shared, target)); ++ if (sd_share) { ++ /* because !--nr is the condition to stop scan */ ++ nr = READ_ONCE(sd_share->nr_idle_scan) + 1; ++ /* overloaded LLC is unlikely to have idle cpu/core */ ++ if (nr == 1) ++ return -1; ++ } ++ } ++ + for_each_cpu_wrap(cpu, cpus, target + 1) { + if (has_idle_core) { + i = select_idle_core(p, cpu, cpus, &idle_cpu); +@@ -9166,6 +9178,77 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu) + return idlest; + } + ++static void update_idle_cpu_scan(struct lb_env *env, ++ unsigned long sum_util) ++{ ++ struct sched_domain_shared *sd_share; ++ int llc_weight, pct; ++ u64 x, y, tmp; ++ /* ++ * Update the number of CPUs to scan in LLC domain, which could ++ * be used as a hint in select_idle_cpu(). The update of sd_share ++ * could be expensive because it is within a shared cache line. ++ * So the write of this hint only occurs during periodic load ++ * balancing, rather than CPU_NEWLY_IDLE, because the latter ++ * can fire way more frequently than the former. ++ */ ++ if (!sched_feat(SIS_UTIL) || env->idle == CPU_NEWLY_IDLE) ++ return; ++ ++ llc_weight = per_cpu(sd_llc_size, env->dst_cpu); ++ if (env->sd->span_weight != llc_weight) ++ return; ++ ++ sd_share = rcu_dereference(per_cpu(sd_llc_shared, env->dst_cpu)); ++ if (!sd_share) ++ return; ++ ++ /* ++ * The number of CPUs to search drops as sum_util increases, when ++ * sum_util hits 85% or above, the scan stops. ++ * The reason to choose 85% as the threshold is because this is the ++ * imbalance_pct(117) when a LLC sched group is overloaded. ++ * ++ * let y = SCHED_CAPACITY_SCALE - p * x^2 [1] ++ * and y'= y / SCHED_CAPACITY_SCALE ++ * ++ * x is the ratio of sum_util compared to the CPU capacity: ++ * x = sum_util / (llc_weight * SCHED_CAPACITY_SCALE) ++ * y' is the ratio of CPUs to be scanned in the LLC domain, ++ * and the number of CPUs to scan is calculated by: ++ * ++ * nr_scan = llc_weight * y' [2] ++ * ++ * When x hits the threshold of overloaded, AKA, when ++ * x = 100 / pct, y drops to 0. According to [1], ++ * p should be SCHED_CAPACITY_SCALE * pct^2 / 10000 ++ * ++ * Scale x by SCHED_CAPACITY_SCALE: ++ * x' = sum_util / llc_weight; [3] ++ * ++ * and finally [1] becomes: ++ * y = SCHED_CAPACITY_SCALE - ++ * x'^2 * pct^2 / (10000 * SCHED_CAPACITY_SCALE) [4] ++ * ++ */ ++ /* equation [3] */ ++ x = sum_util; ++ do_div(x, llc_weight); ++ ++ /* equation [4] */ ++ pct = env->sd->imbalance_pct; ++ tmp = x * x * pct * pct; ++ do_div(tmp, 10000 * SCHED_CAPACITY_SCALE); ++ tmp = min_t(long, tmp, SCHED_CAPACITY_SCALE); ++ y = SCHED_CAPACITY_SCALE - tmp; ++ ++ /* equation [2] */ ++ y *= llc_weight; ++ do_div(y, SCHED_CAPACITY_SCALE); ++ if ((int)y != sd_share->nr_idle_scan) ++ WRITE_ONCE(sd_share->nr_idle_scan, (int)y); ++} ++ + /** + * update_sd_lb_stats - Update sched_domain's statistics for load balancing. + * @env: The load balancing environment. +@@ -9178,6 +9261,7 @@ static inline void update_sd_lb_stats(struct lb_env *env, struct sd_lb_stats *sd + struct sched_group *sg = env->sd->groups; + struct sg_lb_stats *local = &sds->local_stat; + struct sg_lb_stats tmp_sgs; ++ unsigned long sum_util = 0; + int sg_status = 0; + + do { +@@ -9210,6 +9294,7 @@ next_group: + sds->total_load += sgs->group_load; + sds->total_capacity += sgs->group_capacity; + ++ sum_util += sgs->group_util; + sg = sg->next; + } while (sg != env->sd->groups); + +@@ -9235,6 +9320,8 @@ next_group: + WRITE_ONCE(rd->overutilized, SG_OVERUTILIZED); + trace_sched_overutilized_tp(rd, SG_OVERUTILIZED); + } ++ ++ update_idle_cpu_scan(env, sum_util); + } + + #define NUMA_IMBALANCE_MIN 2 +diff --git a/kernel/sched/features.h b/kernel/sched/features.h +index 7f8dace0964c2..c4947c1b5edbe 100644 +--- a/kernel/sched/features.h ++++ b/kernel/sched/features.h +@@ -55,7 +55,8 @@ SCHED_FEAT(TTWU_QUEUE, true) + /* + * When doing wakeups, attempt to limit superfluous scans of the LLC domain. + */ +-SCHED_FEAT(SIS_PROP, true) ++SCHED_FEAT(SIS_PROP, false) ++SCHED_FEAT(SIS_UTIL, true) + + /* + * Issue a WARN when we do multiple update_rq_clock() calls +diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c +index 8007d087a57f9..f75dcd3537b84 100644 +--- a/kernel/sched/rt.c ++++ b/kernel/sched/rt.c +@@ -444,7 +444,7 @@ static inline void rt_queue_push_tasks(struct rq *rq) + #endif /* CONFIG_SMP */ + + static void enqueue_top_rt_rq(struct rt_rq *rt_rq); +-static void dequeue_top_rt_rq(struct rt_rq *rt_rq); ++static void dequeue_top_rt_rq(struct rt_rq *rt_rq, unsigned int count); + + static inline int on_rt_rq(struct sched_rt_entity *rt_se) + { +@@ -565,7 +565,7 @@ static void sched_rt_rq_dequeue(struct rt_rq *rt_rq) + rt_se = rt_rq->tg->rt_se[cpu]; + + if (!rt_se) { +- dequeue_top_rt_rq(rt_rq); ++ dequeue_top_rt_rq(rt_rq, rt_rq->rt_nr_running); + /* Kick cpufreq (see the comment in kernel/sched/sched.h). */ + cpufreq_update_util(rq_of_rt_rq(rt_rq), 0); + } +@@ -651,7 +651,7 @@ static inline void sched_rt_rq_enqueue(struct rt_rq *rt_rq) + + static inline void sched_rt_rq_dequeue(struct rt_rq *rt_rq) + { +- dequeue_top_rt_rq(rt_rq); ++ dequeue_top_rt_rq(rt_rq, rt_rq->rt_nr_running); + } + + static inline int rt_rq_throttled(struct rt_rq *rt_rq) +@@ -1051,7 +1051,7 @@ static void update_curr_rt(struct rq *rq) + } + + static void +-dequeue_top_rt_rq(struct rt_rq *rt_rq) ++dequeue_top_rt_rq(struct rt_rq *rt_rq, unsigned int count) + { + struct rq *rq = rq_of_rt_rq(rt_rq); + +@@ -1062,7 +1062,7 @@ dequeue_top_rt_rq(struct rt_rq *rt_rq) + + BUG_ON(!rq->nr_running); + +- sub_nr_running(rq, rt_rq->rt_nr_running); ++ sub_nr_running(rq, count); + rt_rq->rt_queued = 0; + + } +@@ -1342,18 +1342,21 @@ static void __dequeue_rt_entity(struct sched_rt_entity *rt_se, unsigned int flag + static void dequeue_rt_stack(struct sched_rt_entity *rt_se, unsigned int flags) + { + struct sched_rt_entity *back = NULL; ++ unsigned int rt_nr_running; + + for_each_sched_rt_entity(rt_se) { + rt_se->back = back; + back = rt_se; + } + +- dequeue_top_rt_rq(rt_rq_of_se(back)); ++ rt_nr_running = rt_rq_of_se(back)->rt_nr_running; + + for (rt_se = back; rt_se; rt_se = rt_se->back) { + if (on_rt_rq(rt_se)) + __dequeue_rt_entity(rt_se, flags); + } ++ ++ dequeue_top_rt_rq(rt_rq_of_se(back), rt_nr_running); + } + + static void enqueue_rt_entity(struct sched_rt_entity *rt_se, unsigned int flags) +diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h +index fe8be2f8a47dc..e499028982536 100644 +--- a/kernel/sched/sched.h ++++ b/kernel/sched/sched.h +@@ -348,9 +348,8 @@ extern void __setparam_dl(struct task_struct *p, const struct sched_attr *attr); + extern void __getparam_dl(struct task_struct *p, struct sched_attr *attr); + extern bool __checkparam_dl(const struct sched_attr *attr); + extern bool dl_param_changed(struct task_struct *p, const struct sched_attr *attr); +-extern int dl_task_can_attach(struct task_struct *p, const struct cpumask *cs_cpus_allowed); + extern int dl_cpuset_cpumask_can_shrink(const struct cpumask *cur, const struct cpumask *trial); +-extern bool dl_cpu_busy(unsigned int cpu); ++extern int dl_cpu_busy(int cpu, struct task_struct *p); + + #ifdef CONFIG_CGROUP_SCHED + +@@ -2053,7 +2052,6 @@ static inline int task_on_rq_migrating(struct task_struct *p) + + #define WF_SYNC 0x10 /* Waker goes to sleep after wakeup */ + #define WF_MIGRATED 0x20 /* Internal use, task got migrated */ +-#define WF_ON_CPU 0x40 /* Wakee is on_cpu */ + + #ifdef CONFIG_SMP + static_assert(WF_EXEC == SD_BALANCE_EXEC); +diff --git a/kernel/smp.c b/kernel/smp.c +index b68d63e965db6..82825345432c5 100644 +--- a/kernel/smp.c ++++ b/kernel/smp.c +@@ -174,9 +174,9 @@ static int __init csdlock_debug(char *str) + if (val) + static_branch_enable(&csdlock_debug_enabled); + +- return 0; ++ return 1; + } +-early_param("csdlock_debug", csdlock_debug); ++__setup("csdlock_debug=", csdlock_debug); + + static DEFINE_PER_CPU(call_single_data_t *, cur_csd); + static DEFINE_PER_CPU(smp_call_func_t, cur_csd_func); +diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c +index 0ea8702eb5163..23af5eca11b14 100644 +--- a/kernel/time/hrtimer.c ++++ b/kernel/time/hrtimer.c +@@ -2311,6 +2311,7 @@ schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta, + + return !t.task ? 0 : -EINTR; + } ++EXPORT_SYMBOL_GPL(schedule_hrtimeout_range_clock); + + /** + * schedule_hrtimeout_range - sleep until timeout +diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c +index 871c912860ed5..d6a0ff68df410 100644 +--- a/kernel/time/timekeeping.c ++++ b/kernel/time/timekeeping.c +@@ -23,6 +23,7 @@ + #include <linux/pvclock_gtod.h> + #include <linux/compiler.h> + #include <linux/audit.h> ++#include <linux/random.h> + + #include "tick-internal.h" + #include "ntp_internal.h" +@@ -1326,8 +1327,10 @@ out: + /* Signal hrtimers about time change */ + clock_was_set(CLOCK_SET_WALL); + +- if (!ret) ++ if (!ret) { + audit_tk_injoffset(ts_delta); ++ add_device_randomness(ts, sizeof(*ts)); ++ } + + return ret; + } +@@ -2413,6 +2416,7 @@ int do_adjtimex(struct __kernel_timex *txc) + ret = timekeeping_validate_timex(txc); + if (ret) + return ret; ++ add_device_randomness(txc, sizeof(*txc)); + + if (txc->modes & ADJ_SETOFFSET) { + struct timespec64 delta; +@@ -2430,6 +2434,7 @@ int do_adjtimex(struct __kernel_timex *txc) + audit_ntp_init(&ad); + + ktime_get_real_ts64(&ts); ++ add_device_randomness(&ts, sizeof(ts)); + + raw_spin_lock_irqsave(&timekeeper_lock, flags); + write_seqcount_begin(&tk_core.seq); +diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c +index c42ff77eb6ccc..eaa98e2b468fc 100644 +--- a/kernel/trace/blktrace.c ++++ b/kernel/trace/blktrace.c +@@ -1058,7 +1058,7 @@ static void blk_add_trace_rq_remap(void *ignore, struct request *rq, dev_t dev, + r.sector_from = cpu_to_be64(from); + + __blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq), +- rq_data_dir(rq), 0, BLK_TA_REMAP, 0, ++ req_op(rq), rq->cmd_flags, BLK_TA_REMAP, 0, + sizeof(r), &r, blk_trace_request_get_cgid(rq)); + rcu_read_unlock(); + } +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index d6763366a3206..28ea6c0be4953 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -83,6 +83,9 @@ enum trace_type { + #undef __dynamic_array + #define __dynamic_array(type, item) type item[]; + ++#undef __rel_dynamic_array ++#define __rel_dynamic_array(type, item) type item[]; ++ + #undef F_STRUCT + #define F_STRUCT(args...) args + +diff --git a/lib/crypto/blake2s-selftest.c b/lib/crypto/blake2s-selftest.c +index 409e4b7287704..7d77dea155873 100644 +--- a/lib/crypto/blake2s-selftest.c ++++ b/lib/crypto/blake2s-selftest.c +@@ -4,6 +4,8 @@ + */ + + #include <crypto/internal/blake2s.h> ++#include <linux/kernel.h> ++#include <linux/random.h> + #include <linux/string.h> + + /* +@@ -587,5 +589,44 @@ bool __init blake2s_selftest(void) + } + } + ++ for (i = 0; i < 32; ++i) { ++ enum { TEST_ALIGNMENT = 16 }; ++ u8 unaligned_block[BLAKE2S_BLOCK_SIZE + TEST_ALIGNMENT - 1] ++ __aligned(TEST_ALIGNMENT); ++ u8 blocks[BLAKE2S_BLOCK_SIZE * 2]; ++ struct blake2s_state state1, state2; ++ ++ get_random_bytes(blocks, sizeof(blocks)); ++ get_random_bytes(&state, sizeof(state)); ++ ++#if defined(CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC) && \ ++ defined(CONFIG_CRYPTO_ARCH_HAVE_LIB_BLAKE2S) ++ memcpy(&state1, &state, sizeof(state1)); ++ memcpy(&state2, &state, sizeof(state2)); ++ blake2s_compress(&state1, blocks, 2, BLAKE2S_BLOCK_SIZE); ++ blake2s_compress_generic(&state2, blocks, 2, BLAKE2S_BLOCK_SIZE); ++ if (memcmp(&state1, &state2, sizeof(state1))) { ++ pr_err("blake2s random compress self-test %d: FAIL\n", ++ i + 1); ++ success = false; ++ } ++#endif ++ ++ memcpy(&state1, &state, sizeof(state1)); ++ blake2s_compress(&state1, blocks, 1, BLAKE2S_BLOCK_SIZE); ++ for (l = 1; l < TEST_ALIGNMENT; ++l) { ++ memcpy(unaligned_block + l, blocks, ++ BLAKE2S_BLOCK_SIZE); ++ memcpy(&state2, &state, sizeof(state2)); ++ blake2s_compress(&state2, unaligned_block + l, 1, ++ BLAKE2S_BLOCK_SIZE); ++ if (memcmp(&state1, &state2, sizeof(state1))) { ++ pr_err("blake2s random compress align %d self-test %d: FAIL\n", ++ l, i + 1); ++ success = false; ++ } ++ } ++ } ++ + return success; + } +diff --git a/lib/crypto/blake2s.c b/lib/crypto/blake2s.c +index c71c09621c09c..98e688c6d8910 100644 +--- a/lib/crypto/blake2s.c ++++ b/lib/crypto/blake2s.c +@@ -16,16 +16,44 @@ + #include <linux/init.h> + #include <linux/bug.h> + ++static inline void blake2s_set_lastblock(struct blake2s_state *state) ++{ ++ state->f[0] = -1; ++} ++ + void blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen) + { +- __blake2s_update(state, in, inlen, false); ++ const size_t fill = BLAKE2S_BLOCK_SIZE - state->buflen; ++ ++ if (unlikely(!inlen)) ++ return; ++ if (inlen > fill) { ++ memcpy(state->buf + state->buflen, in, fill); ++ blake2s_compress(state, state->buf, 1, BLAKE2S_BLOCK_SIZE); ++ state->buflen = 0; ++ in += fill; ++ inlen -= fill; ++ } ++ if (inlen > BLAKE2S_BLOCK_SIZE) { ++ const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2S_BLOCK_SIZE); ++ blake2s_compress(state, in, nblocks - 1, BLAKE2S_BLOCK_SIZE); ++ in += BLAKE2S_BLOCK_SIZE * (nblocks - 1); ++ inlen -= BLAKE2S_BLOCK_SIZE * (nblocks - 1); ++ } ++ memcpy(state->buf + state->buflen, in, inlen); ++ state->buflen += inlen; + } + EXPORT_SYMBOL(blake2s_update); + + void blake2s_final(struct blake2s_state *state, u8 *out) + { + WARN_ON(IS_ENABLED(DEBUG) && !out); +- __blake2s_final(state, out, false); ++ blake2s_set_lastblock(state); ++ memset(state->buf + state->buflen, 0, ++ BLAKE2S_BLOCK_SIZE - state->buflen); /* Padding */ ++ blake2s_compress(state, state->buf, 1, state->buflen); ++ cpu_to_le32_array(state->h, ARRAY_SIZE(state->h)); ++ memcpy(out, state->h, state->outlen); + memzero_explicit(state, sizeof(*state)); + } + EXPORT_SYMBOL(blake2s_final); +@@ -38,12 +66,7 @@ static int __init blake2s_mod_init(void) + return 0; + } + +-static void __exit blake2s_mod_exit(void) +-{ +-} +- + module_init(blake2s_mod_init); +-module_exit(blake2s_mod_exit); + MODULE_LICENSE("GPL v2"); + MODULE_DESCRIPTION("BLAKE2s hash function"); + MODULE_AUTHOR("Jason A. Donenfeld <Jason@zx2c4.com>"); +diff --git a/lib/iov_iter.c b/lib/iov_iter.c +index 6cf2d66fb8398..d0c3e939ee601 100644 +--- a/lib/iov_iter.c ++++ b/lib/iov_iter.c +@@ -691,6 +691,7 @@ static size_t copy_mc_pipe_to_iter(const void *addr, size_t bytes, + struct pipe_inode_info *pipe = i->pipe; + unsigned int p_mask = pipe->ring_size - 1; + unsigned int i_head; ++ unsigned int valid = pipe->head; + size_t n, off, xfer = 0; + + if (!sanity(i)) +@@ -704,11 +705,17 @@ static size_t copy_mc_pipe_to_iter(const void *addr, size_t bytes, + rem = copy_mc_to_kernel(p + off, addr + xfer, chunk); + chunk -= rem; + kunmap_local(p); +- i->head = i_head; +- i->iov_offset = off + chunk; +- xfer += chunk; +- if (rem) ++ if (chunk) { ++ i->head = i_head; ++ i->iov_offset = off + chunk; ++ xfer += chunk; ++ valid = i_head + 1; ++ } ++ if (rem) { ++ pipe->bufs[i_head & p_mask].len -= rem; ++ pipe_discard_from(pipe, valid); + break; ++ } + n -= chunk; + off = 0; + i_head++; +diff --git a/lib/livepatch/test_klp_callbacks_busy.c b/lib/livepatch/test_klp_callbacks_busy.c +index 7ac845f65be56..133929e0ce8ff 100644 +--- a/lib/livepatch/test_klp_callbacks_busy.c ++++ b/lib/livepatch/test_klp_callbacks_busy.c +@@ -16,10 +16,12 @@ MODULE_PARM_DESC(block_transition, "block_transition (default=false)"); + + static void busymod_work_func(struct work_struct *work); + static DECLARE_WORK(work, busymod_work_func); ++static DECLARE_COMPLETION(busymod_work_started); + + static void busymod_work_func(struct work_struct *work) + { + pr_info("%s enter\n", __func__); ++ complete(&busymod_work_started); + + while (READ_ONCE(block_transition)) { + /* +@@ -37,6 +39,12 @@ static int test_klp_callbacks_busy_init(void) + pr_info("%s\n", __func__); + schedule_work(&work); + ++ /* ++ * To synchronize kernel messages, hold the init function from ++ * exiting until the work function's entry message has printed. ++ */ ++ wait_for_completion(&busymod_work_started); ++ + if (!block_transition) { + /* + * Serialize output: print all messages from the work +diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c +index 046ac6297c781..a2bb7738c373c 100644 +--- a/lib/smp_processor_id.c ++++ b/lib/smp_processor_id.c +@@ -47,9 +47,9 @@ unsigned int check_preemption_disabled(const char *what1, const char *what2) + + printk("caller is %pS\n", __builtin_return_address(0)); + dump_stack(); +- instrumentation_end(); + + out_enable: ++ instrumentation_end(); + preempt_enable_no_resched_notrace(); + out: + return this_cpu; +diff --git a/lib/test_bpf.c b/lib/test_bpf.c +index 68d125b409f20..84f5dd3b0fc7b 100644 +--- a/lib/test_bpf.c ++++ b/lib/test_bpf.c +@@ -8890,9 +8890,9 @@ static struct skb_segment_test skb_segment_tests[] __initconst = { + .build_skb = build_test_skb_linear_no_head_frag, + .features = NETIF_F_SG | NETIF_F_FRAGLIST | + NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_GSO | +- NETIF_F_LLTX_BIT | NETIF_F_GRO | ++ NETIF_F_LLTX | NETIF_F_GRO | + NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | +- NETIF_F_HW_VLAN_STAG_TX_BIT ++ NETIF_F_HW_VLAN_STAG_TX + } + }; + +diff --git a/lib/test_hmm.c b/lib/test_hmm.c +index ac794e3540693..a89cb4281c9dc 100644 +--- a/lib/test_hmm.c ++++ b/lib/test_hmm.c +@@ -731,7 +731,7 @@ static int dmirror_exclusive(struct dmirror *dmirror, + + mmap_read_lock(mm); + for (addr = start; addr < end; addr = next) { +- unsigned long mapped; ++ unsigned long mapped = 0; + int i; + + if (end < addr + (ARRAY_SIZE(pages) << PAGE_SHIFT)) +@@ -740,7 +740,13 @@ static int dmirror_exclusive(struct dmirror *dmirror, + next = addr + (ARRAY_SIZE(pages) << PAGE_SHIFT); + + ret = make_device_exclusive_range(mm, addr, next, pages, NULL); +- mapped = dmirror_atomic_map(addr, next, pages, dmirror); ++ /* ++ * Do dmirror_atomic_map() iff all pages are marked for ++ * exclusive access to avoid accessing uninitialized ++ * fields of pages. ++ */ ++ if (ret == (next - addr) >> PAGE_SHIFT) ++ mapped = dmirror_atomic_map(addr, next, pages, dmirror); + for (i = 0; i < ret; i++) { + if (pages[i]) { + unlock_page(pages[i]); +diff --git a/lib/test_kasan.c b/lib/test_kasan.c +index 8835e07845785..89f444cabd4a8 100644 +--- a/lib/test_kasan.c ++++ b/lib/test_kasan.c +@@ -125,6 +125,7 @@ static void kmalloc_oob_right(struct kunit *test) + ptr = kmalloc(size, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); + ++ OPTIMIZER_HIDE_VAR(ptr); + /* + * An unaligned access past the requested kmalloc size. + * Only generic KASAN can precisely detect these. +@@ -153,6 +154,7 @@ static void kmalloc_oob_left(struct kunit *test) + ptr = kmalloc(size, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); + ++ OPTIMIZER_HIDE_VAR(ptr); + KUNIT_EXPECT_KASAN_FAIL(test, *ptr = *(ptr - 1)); + kfree(ptr); + } +@@ -165,6 +167,7 @@ static void kmalloc_node_oob_right(struct kunit *test) + ptr = kmalloc_node(size, GFP_KERNEL, 0); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); + ++ OPTIMIZER_HIDE_VAR(ptr); + KUNIT_EXPECT_KASAN_FAIL(test, ptr[0] = ptr[size]); + kfree(ptr); + } +@@ -185,6 +188,7 @@ static void kmalloc_pagealloc_oob_right(struct kunit *test) + ptr = kmalloc(size, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); + ++ OPTIMIZER_HIDE_VAR(ptr); + KUNIT_EXPECT_KASAN_FAIL(test, ptr[size + OOB_TAG_OFF] = 0); + + kfree(ptr); +@@ -265,6 +269,7 @@ static void kmalloc_large_oob_right(struct kunit *test) + ptr = kmalloc(size, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); + ++ OPTIMIZER_HIDE_VAR(ptr); + KUNIT_EXPECT_KASAN_FAIL(test, ptr[size] = 0); + kfree(ptr); + } +@@ -404,6 +409,8 @@ static void kmalloc_oob_16(struct kunit *test) + ptr2 = kmalloc(sizeof(*ptr2), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr2); + ++ OPTIMIZER_HIDE_VAR(ptr1); ++ OPTIMIZER_HIDE_VAR(ptr2); + KUNIT_EXPECT_KASAN_FAIL(test, *ptr1 = *ptr2); + kfree(ptr1); + kfree(ptr2); +@@ -712,6 +719,8 @@ static void ksize_unpoisons_memory(struct kunit *test) + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); + real_size = ksize(ptr); + ++ OPTIMIZER_HIDE_VAR(ptr); ++ + /* This access shouldn't trigger a KASAN report. */ + ptr[size] = 'x'; + +@@ -734,6 +743,7 @@ static void ksize_uaf(struct kunit *test) + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); + kfree(ptr); + ++ OPTIMIZER_HIDE_VAR(ptr); + KUNIT_EXPECT_KASAN_FAIL(test, ksize(ptr)); + KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[0]); + KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[size]); +diff --git a/mm/mempolicy.c b/mm/mempolicy.c +index 9db0158155e1a..4472be6f123db 100644 +--- a/mm/mempolicy.c ++++ b/mm/mempolicy.c +@@ -1389,7 +1389,7 @@ static int get_nodes(nodemask_t *nodes, const unsigned long __user *nmask, + unsigned long bits = min_t(unsigned long, maxnode, BITS_PER_LONG); + unsigned long t; + +- if (get_bitmap(&t, &nmask[maxnode / BITS_PER_LONG], bits)) ++ if (get_bitmap(&t, &nmask[(maxnode - 1) / BITS_PER_LONG], bits)) + return -EFAULT; + + if (maxnode - bits >= MAX_NUMNODES) { +diff --git a/mm/memremap.c b/mm/memremap.c +index e77487375c8ea..8d743cbc29642 100644 +--- a/mm/memremap.c ++++ b/mm/memremap.c +@@ -112,30 +112,6 @@ static unsigned long pfn_next(unsigned long pfn) + #define for_each_device_pfn(pfn, map, i) \ + for (pfn = pfn_first(map, i); pfn < pfn_end(map, i); pfn = pfn_next(pfn)) + +-static void dev_pagemap_kill(struct dev_pagemap *pgmap) +-{ +- if (pgmap->ops && pgmap->ops->kill) +- pgmap->ops->kill(pgmap); +- else +- percpu_ref_kill(pgmap->ref); +-} +- +-static void dev_pagemap_cleanup(struct dev_pagemap *pgmap) +-{ +- if (pgmap->ops && pgmap->ops->cleanup) { +- pgmap->ops->cleanup(pgmap); +- } else { +- wait_for_completion(&pgmap->done); +- percpu_ref_exit(pgmap->ref); +- } +- /* +- * Undo the pgmap ref assignment for the internal case as the +- * caller may re-enable the same pgmap. +- */ +- if (pgmap->ref == &pgmap->internal_ref) +- pgmap->ref = NULL; +-} +- + static void pageunmap_range(struct dev_pagemap *pgmap, int range_id) + { + struct range *range = &pgmap->ranges[range_id]; +@@ -167,14 +143,15 @@ void memunmap_pages(struct dev_pagemap *pgmap) + unsigned long pfn; + int i; + +- dev_pagemap_kill(pgmap); ++ percpu_ref_kill(&pgmap->ref); + for (i = 0; i < pgmap->nr_range; i++) + for_each_device_pfn(pfn, pgmap, i) + put_page(pfn_to_page(pfn)); +- dev_pagemap_cleanup(pgmap); ++ wait_for_completion(&pgmap->done); + + for (i = 0; i < pgmap->nr_range; i++) + pageunmap_range(pgmap, i); ++ percpu_ref_exit(&pgmap->ref); + + WARN_ONCE(pgmap->altmap.alloc, "failed to free all reserved pages\n"); + devmap_managed_enable_put(pgmap); +@@ -188,8 +165,7 @@ static void devm_memremap_pages_release(void *data) + + static void dev_pagemap_percpu_release(struct percpu_ref *ref) + { +- struct dev_pagemap *pgmap = +- container_of(ref, struct dev_pagemap, internal_ref); ++ struct dev_pagemap *pgmap = container_of(ref, struct dev_pagemap, ref); + + complete(&pgmap->done); + } +@@ -295,8 +271,8 @@ static int pagemap_range(struct dev_pagemap *pgmap, struct mhp_params *params, + memmap_init_zone_device(&NODE_DATA(nid)->node_zones[ZONE_DEVICE], + PHYS_PFN(range->start), + PHYS_PFN(range_len(range)), pgmap); +- percpu_ref_get_many(pgmap->ref, pfn_end(pgmap, range_id) +- - pfn_first(pgmap, range_id)); ++ percpu_ref_get_many(&pgmap->ref, ++ pfn_end(pgmap, range_id) - pfn_first(pgmap, range_id)); + return 0; + + err_add_memory: +@@ -362,22 +338,11 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid) + break; + } + +- if (!pgmap->ref) { +- if (pgmap->ops && (pgmap->ops->kill || pgmap->ops->cleanup)) +- return ERR_PTR(-EINVAL); +- +- init_completion(&pgmap->done); +- error = percpu_ref_init(&pgmap->internal_ref, +- dev_pagemap_percpu_release, 0, GFP_KERNEL); +- if (error) +- return ERR_PTR(error); +- pgmap->ref = &pgmap->internal_ref; +- } else { +- if (!pgmap->ops || !pgmap->ops->kill || !pgmap->ops->cleanup) { +- WARN(1, "Missing reference count teardown definition\n"); +- return ERR_PTR(-EINVAL); +- } +- } ++ init_completion(&pgmap->done); ++ error = percpu_ref_init(&pgmap->ref, dev_pagemap_percpu_release, 0, ++ GFP_KERNEL); ++ if (error) ++ return ERR_PTR(error); + + devmap_managed_enable_get(pgmap); + +@@ -486,7 +451,7 @@ struct dev_pagemap *get_dev_pagemap(unsigned long pfn, + /* fall back to slow path lookup */ + rcu_read_lock(); + pgmap = xa_load(&pgmap_array, PHYS_PFN(phys)); +- if (pgmap && !percpu_ref_tryget_live(pgmap->ref)) ++ if (pgmap && !percpu_ref_tryget_live(&pgmap->ref)) + pgmap = NULL; + rcu_read_unlock(); + +diff --git a/mm/mmap.c b/mm/mmap.c +index 6bb553ed5c557..031fca1a7c65e 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -1878,7 +1878,6 @@ unmap_and_free_vma: + + /* Undo any partial mapping done by a device driver. */ + unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end); +- charged = 0; + if (vm_flags & VM_SHARED) + mapping_unmap_writable(file->f_mapping); + free_vma: +diff --git a/net/9p/client.c b/net/9p/client.c +index 7973267ec8464..565aee6dfcc66 100644 +--- a/net/9p/client.c ++++ b/net/9p/client.c +@@ -32,10 +32,9 @@ + + #define DEFAULT_MSIZE (128 * 1024) + +-/* +- * Client Option Parsing (code inspired by NFS code) +- * - a little lazy - parse all client options +- */ ++/* Client Option Parsing (code inspired by NFS code) ++ * - a little lazy - parse all client options ++ */ + + enum { + Opt_msize, +@@ -89,20 +88,18 @@ int p9_show_client_options(struct seq_file *m, struct p9_client *clnt) + } + EXPORT_SYMBOL(p9_show_client_options); + +-/* +- * Some error codes are taken directly from the server replies, ++/* Some error codes are taken directly from the server replies, + * make sure they are valid. + */ + static int safe_errno(int err) + { +- if ((err > 0) || (err < -MAX_ERRNO)) { ++ if (err > 0 || err < -MAX_ERRNO) { + p9_debug(P9_DEBUG_ERROR, "Invalid error code %d\n", err); + return -EPROTO; + } + return err; + } + +- + /* Interpret mount option for protocol version */ + static int get_protocol_version(char *s) + { +@@ -117,8 +114,9 @@ static int get_protocol_version(char *s) + } else if (!strcmp(s, "9p2000.L")) { + version = p9_proto_2000L; + p9_debug(P9_DEBUG_9P, "Protocol version: 9P2000.L\n"); +- } else ++ } else { + pr_info("Unknown protocol version %s\n", s); ++ } + + return version; + } +@@ -147,15 +145,13 @@ static int parse_opts(char *opts, struct p9_client *clnt) + return 0; + + tmp_options = kstrdup(opts, GFP_KERNEL); +- if (!tmp_options) { +- p9_debug(P9_DEBUG_ERROR, +- "failed to allocate copy of option string\n"); ++ if (!tmp_options) + return -ENOMEM; +- } + options = tmp_options; + + while ((p = strsep(&options, ",")) != NULL) { + int token, r; ++ + if (!*p) + continue; + token = match_token(p, tokens, args); +@@ -187,7 +183,7 @@ static int parse_opts(char *opts, struct p9_client *clnt) + + v9fs_put_trans(clnt->trans_mod); + clnt->trans_mod = v9fs_get_trans_by_name(s); +- if (clnt->trans_mod == NULL) { ++ if (!clnt->trans_mod) { + pr_info("Could not find request transport: %s\n", + s); + ret = -EINVAL; +@@ -311,7 +307,7 @@ p9_tag_alloc(struct p9_client *c, int8_t type, unsigned int max_size) + * callback), so p9_client_cb eats the second ref there + * as the pointer is duplicated directly by virtqueue_add_sgs() + */ +- refcount_set(&req->refcount.refcount, 2); ++ refcount_set(&req->refcount, 2); + + return req; + +@@ -347,7 +343,7 @@ again: + if (!p9_req_try_get(req)) + goto again; + if (req->tc.tag != tag) { +- p9_req_put(req); ++ p9_req_put(c, req); + goto again; + } + } +@@ -373,20 +369,18 @@ static int p9_tag_remove(struct p9_client *c, struct p9_req_t *r) + spin_lock_irqsave(&c->lock, flags); + idr_remove(&c->reqs, tag); + spin_unlock_irqrestore(&c->lock, flags); +- return p9_req_put(r); +-} +- +-static void p9_req_free(struct kref *ref) +-{ +- struct p9_req_t *r = container_of(ref, struct p9_req_t, refcount); +- p9_fcall_fini(&r->tc); +- p9_fcall_fini(&r->rc); +- kmem_cache_free(p9_req_cache, r); ++ return p9_req_put(c, r); + } + +-int p9_req_put(struct p9_req_t *r) ++int p9_req_put(struct p9_client *c, struct p9_req_t *r) + { +- return kref_put(&r->refcount, p9_req_free); ++ if (refcount_dec_and_test(&r->refcount)) { ++ p9_fcall_fini(&r->tc); ++ p9_fcall_fini(&r->rc); ++ kmem_cache_free(p9_req_cache, r); ++ return 1; ++ } ++ return 0; + } + EXPORT_SYMBOL(p9_req_put); + +@@ -423,8 +417,7 @@ void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status) + { + p9_debug(P9_DEBUG_MUX, " tag %d\n", req->tc.tag); + +- /* +- * This barrier is needed to make sure any change made to req before ++ /* This barrier is needed to make sure any change made to req before + * the status change is visible to another thread + */ + smp_wmb(); +@@ -432,7 +425,7 @@ void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status) + + wake_up(&req->wq); + p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc.tag); +- p9_req_put(req); ++ p9_req_put(c, req); + } + EXPORT_SYMBOL(p9_client_cb); + +@@ -446,12 +439,12 @@ EXPORT_SYMBOL(p9_client_cb); + */ + + int +-p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type, int16_t *tag, +- int rewind) ++p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type, ++ int16_t *tag, int rewind) + { +- int8_t r_type; +- int16_t r_tag; +- int32_t r_size; ++ s8 r_type; ++ s16 r_tag; ++ s32 r_size; + int offset = pdu->offset; + int err; + +@@ -499,7 +492,7 @@ EXPORT_SYMBOL(p9_parse_header); + + static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) + { +- int8_t type; ++ s8 type; + int err; + int ecode; + +@@ -510,8 +503,7 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) + req->rc.size); + return -EIO; + } +- /* +- * dump the response from server ++ /* dump the response from server + * This should be after check errors which poplulate pdu_fcall. + */ + trace_9p_protocol_dump(c, &req->rc); +@@ -524,6 +516,7 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) + + if (!p9_is_proto_dotl(c)) { + char *ename; ++ + err = p9pdu_readf(&req->rc, c->proto_version, "s?d", + &ename, &ecode); + if (err) +@@ -574,12 +567,11 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req, + { + int err; + int ecode; +- int8_t type; ++ s8 type; + char *ename = NULL; + + err = p9_parse_header(&req->rc, NULL, &type, NULL, 0); +- /* +- * dump the response from server ++ /* dump the response from server + * This should be after parse_header which poplulate pdu_fcall. + */ + trace_9p_protocol_dump(c, &req->rc); +@@ -607,7 +599,7 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req, + if (len > inline_len) { + /* We have error in external buffer */ + if (!copy_from_iter_full(ename + inline_len, +- len - inline_len, uidata)) { ++ len - inline_len, uidata)) { + err = -EFAULT; + goto out_err; + } +@@ -659,7 +651,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); + static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) + { + struct p9_req_t *req; +- int16_t oldtag; ++ s16 oldtag; + int err; + + err = p9_parse_header(&oldreq->tc, NULL, NULL, &oldtag, 1); +@@ -672,8 +664,7 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) + if (IS_ERR(req)) + return PTR_ERR(req); + +- /* +- * if we haven't received a response for oldreq, ++ /* if we haven't received a response for oldreq, + * remove it from the list + */ + if (oldreq->status == REQ_STATUS_SENT) { +@@ -699,7 +690,7 @@ static struct p9_req_t *p9_client_prepare_req(struct p9_client *c, + return ERR_PTR(-EIO); + + /* if status is begin_disconnected we allow only clunk request */ +- if ((c->status == BeginDisconnect) && (type != P9_TCLUNK)) ++ if (c->status == BeginDisconnect && type != P9_TCLUNK) + return ERR_PTR(-EIO); + + req = p9_tag_alloc(c, type, req_size); +@@ -717,7 +708,7 @@ static struct p9_req_t *p9_client_prepare_req(struct p9_client *c, + reterr: + p9_tag_remove(c, req); + /* We have to put also the 2nd reference as it won't be used */ +- p9_req_put(req); ++ p9_req_put(c, req); + return ERR_PTR(err); + } + +@@ -747,13 +738,14 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) + if (signal_pending(current)) { + sigpending = 1; + clear_thread_flag(TIF_SIGPENDING); +- } else ++ } else { + sigpending = 0; ++ } + + err = c->trans_mod->request(c, req); + if (err < 0) { + /* write won't happen */ +- p9_req_put(req); ++ p9_req_put(c, req); + if (err != -ERESTARTSYS && err != -EFAULT) + c->status = Disconnected; + goto recalc_sigpending; +@@ -762,14 +754,13 @@ again: + /* Wait for the response */ + err = wait_event_killable(req->wq, req->status >= REQ_STATUS_RCVD); + +- /* +- * Make sure our req is coherent with regard to updates in other ++ /* Make sure our req is coherent with regard to updates in other + * threads - echoes to wmb() in the callback + */ + smp_rmb(); + +- if ((err == -ERESTARTSYS) && (c->status == Connected) +- && (type == P9_TFLUSH)) { ++ if (err == -ERESTARTSYS && c->status == Connected && ++ type == P9_TFLUSH) { + sigpending = 1; + clear_thread_flag(TIF_SIGPENDING); + goto again; +@@ -779,7 +770,7 @@ again: + p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); + err = req->t_err; + } +- if ((err == -ERESTARTSYS) && (c->status == Connected)) { ++ if (err == -ERESTARTSYS && c->status == Connected) { + p9_debug(P9_DEBUG_MUX, "flushing\n"); + sigpending = 1; + clear_thread_flag(TIF_SIGPENDING); +@@ -834,8 +825,7 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, + struct p9_req_t *req; + + va_start(ap, fmt); +- /* +- * We allocate a inline protocol data of only 4k bytes. ++ /* We allocate a inline protocol data of only 4k bytes. + * The actual content is passed in zero-copy fashion. + */ + req = p9_client_prepare_req(c, type, P9_ZC_HDR_SZ, fmt, ap); +@@ -846,8 +836,9 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, + if (signal_pending(current)) { + sigpending = 1; + clear_thread_flag(TIF_SIGPENDING); +- } else ++ } else { + sigpending = 0; ++ } + + err = c->trans_mod->zc_request(c, req, uidata, uodata, + inlen, olen, in_hdrlen); +@@ -861,7 +852,7 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, + p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); + err = req->t_err; + } +- if ((err == -ERESTARTSYS) && (c->status == Connected)) { ++ if (err == -ERESTARTSYS && c->status == Connected) { + p9_debug(P9_DEBUG_MUX, "flushing\n"); + sigpending = 1; + clear_thread_flag(TIF_SIGPENDING); +@@ -897,16 +888,13 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt) + struct p9_fid *fid; + + p9_debug(P9_DEBUG_FID, "clnt %p\n", clnt); +- fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL); ++ fid = kzalloc(sizeof(*fid), GFP_KERNEL); + if (!fid) + return NULL; + +- memset(&fid->qid, 0, sizeof(struct p9_qid)); + fid->mode = -1; + fid->uid = current_fsuid(); + fid->clnt = clnt; +- fid->rdir = NULL; +- fid->fid = 0; + refcount_set(&fid->count, 1); + + idr_preload(GFP_KERNEL); +@@ -949,15 +937,15 @@ static int p9_client_version(struct p9_client *c) + switch (c->proto_version) { + case p9_proto_2000L: + req = p9_client_rpc(c, P9_TVERSION, "ds", +- c->msize, "9P2000.L"); ++ c->msize, "9P2000.L"); + break; + case p9_proto_2000u: + req = p9_client_rpc(c, P9_TVERSION, "ds", +- c->msize, "9P2000.u"); ++ c->msize, "9P2000.u"); + break; + case p9_proto_legacy: + req = p9_client_rpc(c, P9_TVERSION, "ds", +- c->msize, "9P2000"); ++ c->msize, "9P2000"); + break; + default: + return -EINVAL; +@@ -974,13 +962,13 @@ static int p9_client_version(struct p9_client *c) + } + + p9_debug(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version); +- if (!strncmp(version, "9P2000.L", 8)) ++ if (!strncmp(version, "9P2000.L", 8)) { + c->proto_version = p9_proto_2000L; +- else if (!strncmp(version, "9P2000.u", 8)) ++ } else if (!strncmp(version, "9P2000.u", 8)) { + c->proto_version = p9_proto_2000u; +- else if (!strncmp(version, "9P2000", 6)) ++ } else if (!strncmp(version, "9P2000", 6)) { + c->proto_version = p9_proto_legacy; +- else { ++ } else { + p9_debug(P9_DEBUG_ERROR, + "server returned an unknown version: %s\n", version); + err = -EREMOTEIO; +@@ -1010,7 +998,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) + char *client_id; + + err = 0; +- clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL); ++ clnt = kmalloc(sizeof(*clnt), GFP_KERNEL); + if (!clnt) + return ERR_PTR(-ENOMEM); + +@@ -1032,7 +1020,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) + if (!clnt->trans_mod) + clnt->trans_mod = v9fs_get_default_trans(); + +- if (clnt->trans_mod == NULL) { ++ if (!clnt->trans_mod) { + err = -EPROTONOSUPPORT; + p9_debug(P9_DEBUG_ERROR, + "No transport defined or default transport\n"); +@@ -1120,14 +1108,14 @@ void p9_client_begin_disconnect(struct p9_client *clnt) + EXPORT_SYMBOL(p9_client_begin_disconnect); + + struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, +- const char *uname, kuid_t n_uname, const char *aname) ++ const char *uname, kuid_t n_uname, ++ const char *aname) + { + int err = 0; + struct p9_req_t *req; + struct p9_fid *fid; + struct p9_qid qid; + +- + p9_debug(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n", + afid ? afid->fid : -1, uname, aname); + fid = p9_fid_create(clnt); +@@ -1138,7 +1126,7 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, + fid->uid = n_uname; + + req = p9_client_rpc(clnt, P9_TATTACH, "ddss?u", fid->fid, +- afid ? afid->fid : P9_NOFID, uname, aname, n_uname); ++ afid ? afid->fid : P9_NOFID, uname, aname, n_uname); + if (IS_ERR(req)) { + err = PTR_ERR(req); + goto error; +@@ -1152,7 +1140,7 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, + } + + p9_debug(P9_DEBUG_9P, "<<< RATTACH qid %x.%llx.%x\n", +- qid.type, (unsigned long long)qid.path, qid.version); ++ qid.type, qid.path, qid.version); + + memmove(&fid->qid, &qid, sizeof(struct p9_qid)); + +@@ -1167,14 +1155,14 @@ error: + EXPORT_SYMBOL(p9_client_attach); + + struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname, +- const unsigned char * const *wnames, int clone) ++ const unsigned char * const *wnames, int clone) + { + int err; + struct p9_client *clnt; + struct p9_fid *fid; + struct p9_qid *wqids; + struct p9_req_t *req; +- uint16_t nwqids, count; ++ u16 nwqids, count; + + err = 0; + wqids = NULL; +@@ -1187,14 +1175,14 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname, + } + + fid->uid = oldfid->uid; +- } else ++ } else { + fid = oldfid; +- ++ } + + p9_debug(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %ud wname[0] %s\n", + oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL); + req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid, +- nwname, wnames); ++ nwname, wnames); + if (IS_ERR(req)) { + err = PTR_ERR(req); + goto error; +@@ -1217,9 +1205,9 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname, + + for (count = 0; count < nwqids; count++) + p9_debug(P9_DEBUG_9P, "<<< [%d] %x.%llx.%x\n", +- count, wqids[count].type, +- (unsigned long long)wqids[count].path, +- wqids[count].version); ++ count, wqids[count].type, ++ wqids[count].path, ++ wqids[count].version); + + if (nwname) + memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid)); +@@ -1235,7 +1223,7 @@ clunk_fid: + fid = NULL; + + error: +- if (fid && (fid != oldfid)) ++ if (fid && fid != oldfid) + p9_fid_destroy(fid); + + return ERR_PTR(err); +@@ -1252,7 +1240,7 @@ int p9_client_open(struct p9_fid *fid, int mode) + + clnt = fid->clnt; + p9_debug(P9_DEBUG_9P, ">>> %s fid %d mode %d\n", +- p9_is_proto_dotl(clnt) ? "TLOPEN" : "TOPEN", fid->fid, mode); ++ p9_is_proto_dotl(clnt) ? "TLOPEN" : "TOPEN", fid->fid, mode); + err = 0; + + if (fid->mode != -1) +@@ -1274,8 +1262,8 @@ int p9_client_open(struct p9_fid *fid, int mode) + } + + p9_debug(P9_DEBUG_9P, "<<< %s qid %x.%llx.%x iounit %x\n", +- p9_is_proto_dotl(clnt) ? "RLOPEN" : "ROPEN", qid.type, +- (unsigned long long)qid.path, qid.version, iounit); ++ p9_is_proto_dotl(clnt) ? "RLOPEN" : "ROPEN", qid.type, ++ qid.path, qid.version, iounit); + + memmove(&fid->qid, &qid, sizeof(struct p9_qid)); + fid->mode = mode; +@@ -1288,8 +1276,8 @@ error: + } + EXPORT_SYMBOL(p9_client_open); + +-int p9_client_create_dotl(struct p9_fid *ofid, const char *name, u32 flags, u32 mode, +- kgid_t gid, struct p9_qid *qid) ++int p9_client_create_dotl(struct p9_fid *ofid, const char *name, u32 flags, ++ u32 mode, kgid_t gid, struct p9_qid *qid) + { + int err = 0; + struct p9_client *clnt; +@@ -1297,16 +1285,16 @@ int p9_client_create_dotl(struct p9_fid *ofid, const char *name, u32 flags, u32 + int iounit; + + p9_debug(P9_DEBUG_9P, +- ">>> TLCREATE fid %d name %s flags %d mode %d gid %d\n", +- ofid->fid, name, flags, mode, +- from_kgid(&init_user_ns, gid)); ++ ">>> TLCREATE fid %d name %s flags %d mode %d gid %d\n", ++ ofid->fid, name, flags, mode, ++ from_kgid(&init_user_ns, gid)); + clnt = ofid->clnt; + + if (ofid->mode != -1) + return -EINVAL; + + req = p9_client_rpc(clnt, P9_TLCREATE, "dsddg", ofid->fid, name, flags, +- mode, gid); ++ mode, gid); + if (IS_ERR(req)) { + err = PTR_ERR(req); + goto error; +@@ -1319,9 +1307,7 @@ int p9_client_create_dotl(struct p9_fid *ofid, const char *name, u32 flags, u32 + } + + p9_debug(P9_DEBUG_9P, "<<< RLCREATE qid %x.%llx.%x iounit %x\n", +- qid->type, +- (unsigned long long)qid->path, +- qid->version, iounit); ++ qid->type, qid->path, qid->version, iounit); + + memmove(&ofid->qid, qid, sizeof(struct p9_qid)); + ofid->mode = mode; +@@ -1344,7 +1330,7 @@ int p9_client_fcreate(struct p9_fid *fid, const char *name, u32 perm, int mode, + int iounit; + + p9_debug(P9_DEBUG_9P, ">>> TCREATE fid %d name %s perm %d mode %d\n", +- fid->fid, name, perm, mode); ++ fid->fid, name, perm, mode); + err = 0; + clnt = fid->clnt; + +@@ -1352,7 +1338,7 @@ int p9_client_fcreate(struct p9_fid *fid, const char *name, u32 perm, int mode, + return -EINVAL; + + req = p9_client_rpc(clnt, P9_TCREATE, "dsdb?s", fid->fid, name, perm, +- mode, extension); ++ mode, extension); + if (IS_ERR(req)) { + err = PTR_ERR(req); + goto error; +@@ -1365,9 +1351,7 @@ int p9_client_fcreate(struct p9_fid *fid, const char *name, u32 perm, int mode, + } + + p9_debug(P9_DEBUG_9P, "<<< RCREATE qid %x.%llx.%x iounit %x\n", +- qid.type, +- (unsigned long long)qid.path, +- qid.version, iounit); ++ qid.type, qid.path, qid.version, iounit); + + memmove(&fid->qid, &qid, sizeof(struct p9_qid)); + fid->mode = mode; +@@ -1381,18 +1365,18 @@ error: + EXPORT_SYMBOL(p9_client_fcreate); + + int p9_client_symlink(struct p9_fid *dfid, const char *name, +- const char *symtgt, kgid_t gid, struct p9_qid *qid) ++ const char *symtgt, kgid_t gid, struct p9_qid *qid) + { + int err = 0; + struct p9_client *clnt; + struct p9_req_t *req; + + p9_debug(P9_DEBUG_9P, ">>> TSYMLINK dfid %d name %s symtgt %s\n", +- dfid->fid, name, symtgt); ++ dfid->fid, name, symtgt); + clnt = dfid->clnt; + + req = p9_client_rpc(clnt, P9_TSYMLINK, "dssg", dfid->fid, name, symtgt, +- gid); ++ gid); + if (IS_ERR(req)) { + err = PTR_ERR(req); + goto error; +@@ -1405,7 +1389,7 @@ int p9_client_symlink(struct p9_fid *dfid, const char *name, + } + + p9_debug(P9_DEBUG_9P, "<<< RSYMLINK qid %x.%llx.%x\n", +- qid->type, (unsigned long long)qid->path, qid->version); ++ qid->type, qid->path, qid->version); + + free_and_error: + p9_tag_remove(clnt, req); +@@ -1420,10 +1404,10 @@ int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, const char *newna + struct p9_req_t *req; + + p9_debug(P9_DEBUG_9P, ">>> TLINK dfid %d oldfid %d newname %s\n", +- dfid->fid, oldfid->fid, newname); ++ dfid->fid, oldfid->fid, newname); + clnt = dfid->clnt; + req = p9_client_rpc(clnt, P9_TLINK, "dds", dfid->fid, oldfid->fid, +- newname); ++ newname); + if (IS_ERR(req)) + return PTR_ERR(req); + +@@ -1440,7 +1424,7 @@ int p9_client_fsync(struct p9_fid *fid, int datasync) + struct p9_req_t *req; + + p9_debug(P9_DEBUG_9P, ">>> TFSYNC fid %d datasync:%d\n", +- fid->fid, datasync); ++ fid->fid, datasync); + err = 0; + clnt = fid->clnt; + +@@ -1476,8 +1460,8 @@ int p9_client_clunk(struct p9_fid *fid) + return 0; + + again: +- p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d (try %d)\n", fid->fid, +- retries); ++ p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d (try %d)\n", ++ fid->fid, retries); + err = 0; + clnt = fid->clnt; + +@@ -1491,16 +1475,16 @@ again: + + p9_tag_remove(clnt, req); + error: +- /* +- * Fid is not valid even after a failed clunk ++ /* Fid is not valid even after a failed clunk + * If interrupted, retry once then give up and + * leak fid until umount. + */ + if (err == -ERESTARTSYS) { + if (retries++ == 0) + goto again; +- } else ++ } else { + p9_fid_destroy(fid); ++ } + return err; + } + EXPORT_SYMBOL(p9_client_clunk); +@@ -1540,7 +1524,7 @@ int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags) + struct p9_client *clnt; + + p9_debug(P9_DEBUG_9P, ">>> TUNLINKAT fid %d %s %d\n", +- dfid->fid, name, flags); ++ dfid->fid, name, flags); + + clnt = dfid->clnt; + req = p9_client_rpc(clnt, P9_TUNLINKAT, "dsd", dfid->fid, name, flags); +@@ -1586,8 +1570,8 @@ p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to, + char *dataptr; + + *err = 0; +- p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", +- fid->fid, (unsigned long long) offset, (int)iov_iter_count(to)); ++ p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %zu\n", ++ fid->fid, offset, iov_iter_count(to)); + + rsize = fid->iounit; + if (!rsize || rsize > clnt->msize - P9_IOHDRSZ) +@@ -1653,13 +1637,13 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err) + *err = 0; + + p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %zd\n", +- fid->fid, (unsigned long long) offset, +- iov_iter_count(from)); ++ fid->fid, offset, iov_iter_count(from)); + + while (iov_iter_count(from)) { + int count = iov_iter_count(from); + int rsize = fid->iounit; +- if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) ++ ++ if (!rsize || rsize > clnt->msize - P9_IOHDRSZ) + rsize = clnt->msize - P9_IOHDRSZ; + + if (count < rsize) +@@ -1672,7 +1656,7 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err) + fid->fid, offset, rsize); + } else { + req = p9_client_rpc(clnt, P9_TWRITE, "dqV", fid->fid, +- offset, rsize, from); ++ offset, rsize, from); + } + if (IS_ERR(req)) { + *err = PTR_ERR(req); +@@ -1705,12 +1689,13 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid) + { + int err; + struct p9_client *clnt; +- struct p9_wstat *ret = kmalloc(sizeof(struct p9_wstat), GFP_KERNEL); ++ struct p9_wstat *ret; + struct p9_req_t *req; + u16 ignored; + + p9_debug(P9_DEBUG_9P, ">>> TSTAT fid %d\n", fid->fid); + ++ ret = kmalloc(sizeof(*ret), GFP_KERNEL); + if (!ret) + return ERR_PTR(-ENOMEM); + +@@ -1731,17 +1716,17 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid) + } + + p9_debug(P9_DEBUG_9P, +- "<<< RSTAT sz=%x type=%x dev=%x qid=%x.%llx.%x\n" +- "<<< mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n" +- "<<< name=%s uid=%s gid=%s muid=%s extension=(%s)\n" +- "<<< uid=%d gid=%d n_muid=%d\n", +- ret->size, ret->type, ret->dev, ret->qid.type, +- (unsigned long long)ret->qid.path, ret->qid.version, ret->mode, +- ret->atime, ret->mtime, (unsigned long long)ret->length, +- ret->name, ret->uid, ret->gid, ret->muid, ret->extension, +- from_kuid(&init_user_ns, ret->n_uid), +- from_kgid(&init_user_ns, ret->n_gid), +- from_kuid(&init_user_ns, ret->n_muid)); ++ "<<< RSTAT sz=%x type=%x dev=%x qid=%x.%llx.%x\n" ++ "<<< mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n" ++ "<<< name=%s uid=%s gid=%s muid=%s extension=(%s)\n" ++ "<<< uid=%d gid=%d n_muid=%d\n", ++ ret->size, ret->type, ret->dev, ret->qid.type, ret->qid.path, ++ ret->qid.version, ret->mode, ++ ret->atime, ret->mtime, ret->length, ++ ret->name, ret->uid, ret->gid, ret->muid, ret->extension, ++ from_kuid(&init_user_ns, ret->n_uid), ++ from_kgid(&init_user_ns, ret->n_gid), ++ from_kuid(&init_user_ns, ret->n_muid)); + + p9_tag_remove(clnt, req); + return ret; +@@ -1753,17 +1738,17 @@ error: + EXPORT_SYMBOL(p9_client_stat); + + struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid, +- u64 request_mask) ++ u64 request_mask) + { + int err; + struct p9_client *clnt; +- struct p9_stat_dotl *ret = kmalloc(sizeof(struct p9_stat_dotl), +- GFP_KERNEL); ++ struct p9_stat_dotl *ret; + struct p9_req_t *req; + + p9_debug(P9_DEBUG_9P, ">>> TGETATTR fid %d, request_mask %lld\n", +- fid->fid, request_mask); ++ fid->fid, request_mask); + ++ ret = kmalloc(sizeof(*ret), GFP_KERNEL); + if (!ret) + return ERR_PTR(-ENOMEM); + +@@ -1783,26 +1768,27 @@ struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid, + goto error; + } + +- p9_debug(P9_DEBUG_9P, +- "<<< RGETATTR st_result_mask=%lld\n" +- "<<< qid=%x.%llx.%x\n" +- "<<< st_mode=%8.8x st_nlink=%llu\n" +- "<<< st_uid=%d st_gid=%d\n" +- "<<< st_rdev=%llx st_size=%llx st_blksize=%llu st_blocks=%llu\n" +- "<<< st_atime_sec=%lld st_atime_nsec=%lld\n" +- "<<< st_mtime_sec=%lld st_mtime_nsec=%lld\n" +- "<<< st_ctime_sec=%lld st_ctime_nsec=%lld\n" +- "<<< st_btime_sec=%lld st_btime_nsec=%lld\n" +- "<<< st_gen=%lld st_data_version=%lld\n", +- ret->st_result_mask, ret->qid.type, ret->qid.path, +- ret->qid.version, ret->st_mode, ret->st_nlink, +- from_kuid(&init_user_ns, ret->st_uid), +- from_kgid(&init_user_ns, ret->st_gid), +- ret->st_rdev, ret->st_size, ret->st_blksize, +- ret->st_blocks, ret->st_atime_sec, ret->st_atime_nsec, +- ret->st_mtime_sec, ret->st_mtime_nsec, ret->st_ctime_sec, +- ret->st_ctime_nsec, ret->st_btime_sec, ret->st_btime_nsec, +- ret->st_gen, ret->st_data_version); ++ p9_debug(P9_DEBUG_9P, "<<< RGETATTR st_result_mask=%lld\n" ++ "<<< qid=%x.%llx.%x\n" ++ "<<< st_mode=%8.8x st_nlink=%llu\n" ++ "<<< st_uid=%d st_gid=%d\n" ++ "<<< st_rdev=%llx st_size=%llx st_blksize=%llu st_blocks=%llu\n" ++ "<<< st_atime_sec=%lld st_atime_nsec=%lld\n" ++ "<<< st_mtime_sec=%lld st_mtime_nsec=%lld\n" ++ "<<< st_ctime_sec=%lld st_ctime_nsec=%lld\n" ++ "<<< st_btime_sec=%lld st_btime_nsec=%lld\n" ++ "<<< st_gen=%lld st_data_version=%lld\n", ++ ret->st_result_mask, ++ ret->qid.type, ret->qid.path, ret->qid.version, ++ ret->st_mode, ret->st_nlink, ++ from_kuid(&init_user_ns, ret->st_uid), ++ from_kgid(&init_user_ns, ret->st_gid), ++ ret->st_rdev, ret->st_size, ret->st_blksize, ret->st_blocks, ++ ret->st_atime_sec, ret->st_atime_nsec, ++ ret->st_mtime_sec, ret->st_mtime_nsec, ++ ret->st_ctime_sec, ret->st_ctime_nsec, ++ ret->st_btime_sec, ret->st_btime_nsec, ++ ret->st_gen, ret->st_data_version); + + p9_tag_remove(clnt, req); + return ret; +@@ -1821,7 +1807,7 @@ static int p9_client_statsize(struct p9_wstat *wst, int proto_version) + /* size[2] type[2] dev[4] qid[13] */ + /* mode[4] atime[4] mtime[4] length[8]*/ + /* name[s] uid[s] gid[s] muid[s] */ +- ret = 2+4+13+4+4+4+8+2+2+2+2; ++ ret = 2 + 4 + 13 + 4 + 4 + 4 + 8 + 2 + 2 + 2 + 2; + + if (wst->name) + ret += strlen(wst->name); +@@ -1832,9 +1818,10 @@ static int p9_client_statsize(struct p9_wstat *wst, int proto_version) + if (wst->muid) + ret += strlen(wst->muid); + +- if ((proto_version == p9_proto_2000u) || +- (proto_version == p9_proto_2000L)) { +- ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */ ++ if (proto_version == p9_proto_2000u || ++ proto_version == p9_proto_2000L) { ++ /* extension[s] n_uid[4] n_gid[4] n_muid[4] */ ++ ret += 2 + 4 + 4 + 4; + if (wst->extension) + ret += strlen(wst->extension); + } +@@ -1851,21 +1838,23 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) + err = 0; + clnt = fid->clnt; + wst->size = p9_client_statsize(wst, clnt->proto_version); +- p9_debug(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid); ++ p9_debug(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", ++ fid->fid); + p9_debug(P9_DEBUG_9P, +- " sz=%x type=%x dev=%x qid=%x.%llx.%x\n" +- " mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n" +- " name=%s uid=%s gid=%s muid=%s extension=(%s)\n" +- " uid=%d gid=%d n_muid=%d\n", +- wst->size, wst->type, wst->dev, wst->qid.type, +- (unsigned long long)wst->qid.path, wst->qid.version, wst->mode, +- wst->atime, wst->mtime, (unsigned long long)wst->length, +- wst->name, wst->uid, wst->gid, wst->muid, wst->extension, +- from_kuid(&init_user_ns, wst->n_uid), +- from_kgid(&init_user_ns, wst->n_gid), +- from_kuid(&init_user_ns, wst->n_muid)); +- +- req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size+2, wst); ++ " sz=%x type=%x dev=%x qid=%x.%llx.%x\n" ++ " mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n" ++ " name=%s uid=%s gid=%s muid=%s extension=(%s)\n" ++ " uid=%d gid=%d n_muid=%d\n", ++ wst->size, wst->type, wst->dev, wst->qid.type, ++ wst->qid.path, wst->qid.version, ++ wst->mode, wst->atime, wst->mtime, wst->length, ++ wst->name, wst->uid, wst->gid, wst->muid, wst->extension, ++ from_kuid(&init_user_ns, wst->n_uid), ++ from_kgid(&init_user_ns, wst->n_gid), ++ from_kuid(&init_user_ns, wst->n_muid)); ++ ++ req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", ++ fid->fid, wst->size + 2, wst); + if (IS_ERR(req)) { + err = PTR_ERR(req); + goto error; +@@ -1888,15 +1877,15 @@ int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *p9attr) + err = 0; + clnt = fid->clnt; + p9_debug(P9_DEBUG_9P, ">>> TSETATTR fid %d\n", fid->fid); +- p9_debug(P9_DEBUG_9P, +- " valid=%x mode=%x uid=%d gid=%d size=%lld\n" +- " atime_sec=%lld atime_nsec=%lld\n" +- " mtime_sec=%lld mtime_nsec=%lld\n", +- p9attr->valid, p9attr->mode, +- from_kuid(&init_user_ns, p9attr->uid), +- from_kgid(&init_user_ns, p9attr->gid), +- p9attr->size, p9attr->atime_sec, p9attr->atime_nsec, +- p9attr->mtime_sec, p9attr->mtime_nsec); ++ p9_debug(P9_DEBUG_9P, " valid=%x mode=%x uid=%d gid=%d size=%lld\n", ++ p9attr->valid, p9attr->mode, ++ from_kuid(&init_user_ns, p9attr->uid), ++ from_kgid(&init_user_ns, p9attr->gid), ++ p9attr->size); ++ p9_debug(P9_DEBUG_9P, " atime_sec=%lld atime_nsec=%lld\n", ++ p9attr->atime_sec, p9attr->atime_nsec); ++ p9_debug(P9_DEBUG_9P, " mtime_sec=%lld mtime_nsec=%lld\n", ++ p9attr->mtime_sec, p9attr->mtime_nsec); + + req = p9_client_rpc(clnt, P9_TSETATTR, "dI", fid->fid, p9attr); + +@@ -1937,12 +1926,10 @@ int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb) + goto error; + } + +- p9_debug(P9_DEBUG_9P, "<<< RSTATFS fid %d type 0x%lx bsize %ld " +- "blocks %llu bfree %llu bavail %llu files %llu ffree %llu " +- "fsid %llu namelen %ld\n", +- fid->fid, (long unsigned int)sb->type, (long int)sb->bsize, +- sb->blocks, sb->bfree, sb->bavail, sb->files, sb->ffree, +- sb->fsid, (long int)sb->namelen); ++ p9_debug(P9_DEBUG_9P, ++ "<<< RSTATFS fid %d type 0x%x bsize %u blocks %llu bfree %llu bavail %llu files %llu ffree %llu fsid %llu namelen %u\n", ++ fid->fid, sb->type, sb->bsize, sb->blocks, sb->bfree, ++ sb->bavail, sb->files, sb->ffree, sb->fsid, sb->namelen); + + p9_tag_remove(clnt, req); + error: +@@ -1961,10 +1948,10 @@ int p9_client_rename(struct p9_fid *fid, + clnt = fid->clnt; + + p9_debug(P9_DEBUG_9P, ">>> TRENAME fid %d newdirfid %d name %s\n", +- fid->fid, newdirfid->fid, name); ++ fid->fid, newdirfid->fid, name); + + req = p9_client_rpc(clnt, P9_TRENAME, "dds", fid->fid, +- newdirfid->fid, name); ++ newdirfid->fid, name); + if (IS_ERR(req)) { + err = PTR_ERR(req); + goto error; +@@ -1988,9 +1975,9 @@ int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name, + err = 0; + clnt = olddirfid->clnt; + +- p9_debug(P9_DEBUG_9P, ">>> TRENAMEAT olddirfid %d old name %s" +- " newdirfid %d new name %s\n", olddirfid->fid, old_name, +- newdirfid->fid, new_name); ++ p9_debug(P9_DEBUG_9P, ++ ">>> TRENAMEAT olddirfid %d old name %s newdirfid %d new name %s\n", ++ olddirfid->fid, old_name, newdirfid->fid, new_name); + + req = p9_client_rpc(clnt, P9_TRENAMEAT, "dsds", olddirfid->fid, + old_name, newdirfid->fid, new_name); +@@ -2000,7 +1987,7 @@ int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name, + } + + p9_debug(P9_DEBUG_9P, "<<< RRENAMEAT newdirfid %d new name %s\n", +- newdirfid->fid, new_name); ++ newdirfid->fid, new_name); + + p9_tag_remove(clnt, req); + error: +@@ -2008,11 +1995,10 @@ error: + } + EXPORT_SYMBOL(p9_client_renameat); + +-/* +- * An xattrwalk without @attr_name gives the fid for the lisxattr namespace ++/* An xattrwalk without @attr_name gives the fid for the lisxattr namespace + */ + struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid, +- const char *attr_name, u64 *attr_size) ++ const char *attr_name, u64 *attr_size) + { + int err; + struct p9_req_t *req; +@@ -2027,11 +2013,11 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid, + goto error; + } + p9_debug(P9_DEBUG_9P, +- ">>> TXATTRWALK file_fid %d, attr_fid %d name %s\n", +- file_fid->fid, attr_fid->fid, attr_name); ++ ">>> TXATTRWALK file_fid %d, attr_fid %d name %s\n", ++ file_fid->fid, attr_fid->fid, attr_name); + + req = p9_client_rpc(clnt, P9_TXATTRWALK, "dds", +- file_fid->fid, attr_fid->fid, attr_name); ++ file_fid->fid, attr_fid->fid, attr_name); + if (IS_ERR(req)) { + err = PTR_ERR(req); + goto error; +@@ -2044,13 +2030,13 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid, + } + p9_tag_remove(clnt, req); + p9_debug(P9_DEBUG_9P, "<<< RXATTRWALK fid %d size %llu\n", +- attr_fid->fid, *attr_size); ++ attr_fid->fid, *attr_size); + return attr_fid; + clunk_fid: + p9_client_clunk(attr_fid); + attr_fid = NULL; + error: +- if (attr_fid && (attr_fid != file_fid)) ++ if (attr_fid && attr_fid != file_fid) + p9_fid_destroy(attr_fid); + + return ERR_PTR(err); +@@ -2058,19 +2044,19 @@ error: + EXPORT_SYMBOL_GPL(p9_client_xattrwalk); + + int p9_client_xattrcreate(struct p9_fid *fid, const char *name, +- u64 attr_size, int flags) ++ u64 attr_size, int flags) + { + int err; + struct p9_req_t *req; + struct p9_client *clnt; + + p9_debug(P9_DEBUG_9P, +- ">>> TXATTRCREATE fid %d name %s size %lld flag %d\n", +- fid->fid, name, (long long)attr_size, flags); ++ ">>> TXATTRCREATE fid %d name %s size %llu flag %d\n", ++ fid->fid, name, attr_size, flags); + err = 0; + clnt = fid->clnt; + req = p9_client_rpc(clnt, P9_TXATTRCREATE, "dsqd", +- fid->fid, name, attr_size, flags); ++ fid->fid, name, attr_size, flags); + if (IS_ERR(req)) { + err = PTR_ERR(req); + goto error; +@@ -2094,13 +2080,13 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) + iov_iter_kvec(&to, READ, &kv, 1, count); + + p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n", +- fid->fid, (unsigned long long) offset, count); ++ fid->fid, offset, count); + + err = 0; + clnt = fid->clnt; + + rsize = fid->iounit; +- if (!rsize || rsize > clnt->msize-P9_READDIRHDRSZ) ++ if (!rsize || rsize > clnt->msize - P9_READDIRHDRSZ) + rsize = clnt->msize - P9_READDIRHDRSZ; + + if (count < rsize) +@@ -2108,8 +2094,7 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) + + /* Don't bother zerocopy for small IO (< 1024) */ + if (clnt->trans_mod->zc_request && rsize > 1024) { +- /* +- * response header len is 11 ++ /* response header len is 11 + * PDU Header(7) + IO Size (4) + */ + req = p9_client_zc_rpc(clnt, P9_TREADDIR, &to, NULL, rsize, 0, +@@ -2150,7 +2135,7 @@ error: + EXPORT_SYMBOL(p9_client_readdir); + + int p9_client_mknod_dotl(struct p9_fid *fid, const char *name, int mode, +- dev_t rdev, kgid_t gid, struct p9_qid *qid) ++ dev_t rdev, kgid_t gid, struct p9_qid *qid) + { + int err; + struct p9_client *clnt; +@@ -2158,10 +2143,11 @@ int p9_client_mknod_dotl(struct p9_fid *fid, const char *name, int mode, + + err = 0; + clnt = fid->clnt; +- p9_debug(P9_DEBUG_9P, ">>> TMKNOD fid %d name %s mode %d major %d " +- "minor %d\n", fid->fid, name, mode, MAJOR(rdev), MINOR(rdev)); ++ p9_debug(P9_DEBUG_9P, ++ ">>> TMKNOD fid %d name %s mode %d major %d minor %d\n", ++ fid->fid, name, mode, MAJOR(rdev), MINOR(rdev)); + req = p9_client_rpc(clnt, P9_TMKNOD, "dsdddg", fid->fid, name, mode, +- MAJOR(rdev), MINOR(rdev), gid); ++ MAJOR(rdev), MINOR(rdev), gid); + if (IS_ERR(req)) + return PTR_ERR(req); + +@@ -2170,18 +2156,17 @@ int p9_client_mknod_dotl(struct p9_fid *fid, const char *name, int mode, + trace_9p_protocol_dump(clnt, &req->rc); + goto error; + } +- p9_debug(P9_DEBUG_9P, "<<< RMKNOD qid %x.%llx.%x\n", qid->type, +- (unsigned long long)qid->path, qid->version); ++ p9_debug(P9_DEBUG_9P, "<<< RMKNOD qid %x.%llx.%x\n", ++ qid->type, qid->path, qid->version); + + error: + p9_tag_remove(clnt, req); + return err; +- + } + EXPORT_SYMBOL(p9_client_mknod_dotl); + + int p9_client_mkdir_dotl(struct p9_fid *fid, const char *name, int mode, +- kgid_t gid, struct p9_qid *qid) ++ kgid_t gid, struct p9_qid *qid) + { + int err; + struct p9_client *clnt; +@@ -2191,8 +2176,8 @@ int p9_client_mkdir_dotl(struct p9_fid *fid, const char *name, int mode, + clnt = fid->clnt; + p9_debug(P9_DEBUG_9P, ">>> TMKDIR fid %d name %s mode %d gid %d\n", + fid->fid, name, mode, from_kgid(&init_user_ns, gid)); +- req = p9_client_rpc(clnt, P9_TMKDIR, "dsdg", fid->fid, name, mode, +- gid); ++ req = p9_client_rpc(clnt, P9_TMKDIR, "dsdg", ++ fid->fid, name, mode, gid); + if (IS_ERR(req)) + return PTR_ERR(req); + +@@ -2202,12 +2187,11 @@ int p9_client_mkdir_dotl(struct p9_fid *fid, const char *name, int mode, + goto error; + } + p9_debug(P9_DEBUG_9P, "<<< RMKDIR qid %x.%llx.%x\n", qid->type, +- (unsigned long long)qid->path, qid->version); ++ qid->path, qid->version); + + error: + p9_tag_remove(clnt, req); + return err; +- + } + EXPORT_SYMBOL(p9_client_mkdir_dotl); + +@@ -2219,14 +2203,14 @@ int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status) + + err = 0; + clnt = fid->clnt; +- p9_debug(P9_DEBUG_9P, ">>> TLOCK fid %d type %i flags %d " +- "start %lld length %lld proc_id %d client_id %s\n", +- fid->fid, flock->type, flock->flags, flock->start, +- flock->length, flock->proc_id, flock->client_id); ++ p9_debug(P9_DEBUG_9P, ++ ">>> TLOCK fid %d type %i flags %d start %lld length %lld proc_id %d client_id %s\n", ++ fid->fid, flock->type, flock->flags, flock->start, ++ flock->length, flock->proc_id, flock->client_id); + + req = p9_client_rpc(clnt, P9_TLOCK, "dbdqqds", fid->fid, flock->type, +- flock->flags, flock->start, flock->length, +- flock->proc_id, flock->client_id); ++ flock->flags, flock->start, flock->length, ++ flock->proc_id, flock->client_id); + + if (IS_ERR(req)) + return PTR_ERR(req); +@@ -2240,7 +2224,6 @@ int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status) + error: + p9_tag_remove(clnt, req); + return err; +- + } + EXPORT_SYMBOL(p9_client_lock_dotl); + +@@ -2252,12 +2235,14 @@ int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock) + + err = 0; + clnt = fid->clnt; +- p9_debug(P9_DEBUG_9P, ">>> TGETLOCK fid %d, type %i start %lld " +- "length %lld proc_id %d client_id %s\n", fid->fid, glock->type, +- glock->start, glock->length, glock->proc_id, glock->client_id); ++ p9_debug(P9_DEBUG_9P, ++ ">>> TGETLOCK fid %d, type %i start %lld length %lld proc_id %d client_id %s\n", ++ fid->fid, glock->type, glock->start, glock->length, ++ glock->proc_id, glock->client_id); + +- req = p9_client_rpc(clnt, P9_TGETLOCK, "dbqqds", fid->fid, glock->type, +- glock->start, glock->length, glock->proc_id, glock->client_id); ++ req = p9_client_rpc(clnt, P9_TGETLOCK, "dbqqds", fid->fid, ++ glock->type, glock->start, glock->length, ++ glock->proc_id, glock->client_id); + + if (IS_ERR(req)) + return PTR_ERR(req); +@@ -2269,9 +2254,10 @@ int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock) + trace_9p_protocol_dump(clnt, &req->rc); + goto error; + } +- p9_debug(P9_DEBUG_9P, "<<< RGETLOCK type %i start %lld length %lld " +- "proc_id %d client_id %s\n", glock->type, glock->start, +- glock->length, glock->proc_id, glock->client_id); ++ p9_debug(P9_DEBUG_9P, ++ "<<< RGETLOCK type %i start %lld length %lld proc_id %d client_id %s\n", ++ glock->type, glock->start, glock->length, ++ glock->proc_id, glock->client_id); + error: + p9_tag_remove(clnt, req); + return err; +diff --git a/net/9p/error.c b/net/9p/error.c +index 61c18daf3050a..ff935746754e0 100644 +--- a/net/9p/error.c ++++ b/net/9p/error.c +@@ -185,7 +185,7 @@ int p9_error_init(void) + INIT_HLIST_HEAD(&hash_errmap[bucket]); + + /* load initial error map into hash table */ +- for (c = errmap; c->name != NULL; c++) { ++ for (c = errmap; c->name; c++) { + c->namelen = strlen(c->name); + bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ; + INIT_HLIST_NODE(&c->list); +diff --git a/net/9p/mod.c b/net/9p/mod.c +index 5126566850bd0..535cf016633c7 100644 +--- a/net/9p/mod.c ++++ b/net/9p/mod.c +@@ -24,13 +24,13 @@ + #include <linux/spinlock.h> + + #ifdef CONFIG_NET_9P_DEBUG +-unsigned int p9_debug_level = 0; /* feature-rific global debug level */ ++unsigned int p9_debug_level; /* feature-rific global debug level */ + EXPORT_SYMBOL(p9_debug_level); + module_param_named(debug, p9_debug_level, uint, 0); + MODULE_PARM_DESC(debug, "9P debugging level"); + + void _p9_debug(enum p9_debug_flags level, const char *func, +- const char *fmt, ...) ++ const char *fmt, ...) + { + struct va_format vaf; + va_list args; +@@ -53,10 +53,7 @@ void _p9_debug(enum p9_debug_flags level, const char *func, + EXPORT_SYMBOL(_p9_debug); + #endif + +-/* +- * Dynamic Transport Registration Routines +- * +- */ ++/* Dynamic Transport Registration Routines */ + + static DEFINE_SPINLOCK(v9fs_trans_lock); + static LIST_HEAD(v9fs_trans_list); +diff --git a/net/9p/protocol.c b/net/9p/protocol.c +index 03593eb240d87..59eb71f357fa7 100644 +--- a/net/9p/protocol.c ++++ b/net/9p/protocol.c +@@ -46,6 +46,7 @@ EXPORT_SYMBOL(p9stat_free); + size_t pdu_read(struct p9_fcall *pdu, void *data, size_t size) + { + size_t len = min(pdu->size - pdu->offset, size); ++ + memcpy(data, &pdu->sdata[pdu->offset], len); + pdu->offset += len; + return size - len; +@@ -54,6 +55,7 @@ size_t pdu_read(struct p9_fcall *pdu, void *data, size_t size) + static size_t pdu_write(struct p9_fcall *pdu, const void *data, size_t size) + { + size_t len = min(pdu->capacity - pdu->size, size); ++ + memcpy(&pdu->sdata[pdu->size], data, len); + pdu->size += len; + return size - len; +@@ -64,6 +66,7 @@ pdu_write_u(struct p9_fcall *pdu, struct iov_iter *from, size_t size) + { + size_t len = min(pdu->capacity - pdu->size, size); + struct iov_iter i = *from; ++ + if (!copy_from_iter_full(&pdu->sdata[pdu->size], len, &i)) + len = 0; + +@@ -71,26 +74,25 @@ pdu_write_u(struct p9_fcall *pdu, struct iov_iter *from, size_t size) + return size - len; + } + +-/* +- b - int8_t +- w - int16_t +- d - int32_t +- q - int64_t +- s - string +- u - numeric uid +- g - numeric gid +- S - stat +- Q - qid +- D - data blob (int32_t size followed by void *, results are not freed) +- T - array of strings (int16_t count, followed by strings) +- R - array of qids (int16_t count, followed by qids) +- A - stat for 9p2000.L (p9_stat_dotl) +- ? - if optional = 1, continue parsing +-*/ ++/* b - int8_t ++ * w - int16_t ++ * d - int32_t ++ * q - int64_t ++ * s - string ++ * u - numeric uid ++ * g - numeric gid ++ * S - stat ++ * Q - qid ++ * D - data blob (int32_t size followed by void *, results are not freed) ++ * T - array of strings (int16_t count, followed by strings) ++ * R - array of qids (int16_t count, followed by qids) ++ * A - stat for 9p2000.L (p9_stat_dotl) ++ * ? - if optional = 1, continue parsing ++ */ + + static int + p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, +- va_list ap) ++ va_list ap) + { + const char *ptr; + int errcode = 0; +diff --git a/net/9p/protocol.h b/net/9p/protocol.h +index 6835f91cfda59..4a2f686510371 100644 +--- a/net/9p/protocol.h ++++ b/net/9p/protocol.h +@@ -11,7 +11,7 @@ + */ + + int p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, +- va_list ap); ++ va_list ap); + int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...); + int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type); + int p9pdu_finalize(struct p9_client *clnt, struct p9_fcall *pdu); +diff --git a/net/9p/trans_common.h b/net/9p/trans_common.h +index c43babb3f6354..65c094c321a29 100644 +--- a/net/9p/trans_common.h ++++ b/net/9p/trans_common.h +@@ -12,4 +12,4 @@ + * + */ + +-void p9_release_pages(struct page **, int); ++void p9_release_pages(struct page **pages, int nr_pages); +diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c +index 007bbcc68010b..6fe3719c1fc61 100644 +--- a/net/9p/trans_fd.c ++++ b/net/9p/trans_fd.c +@@ -345,6 +345,7 @@ static void p9_read_work(struct work_struct *work) + p9_debug(P9_DEBUG_ERROR, + "No recv fcall for tag %d (req %p), disconnecting!\n", + m->rc.tag, m->rreq); ++ p9_req_put(m->client, m->rreq); + m->rreq = NULL; + err = -EIO; + goto error; +@@ -380,7 +381,7 @@ static void p9_read_work(struct work_struct *work) + m->rc.sdata = NULL; + m->rc.offset = 0; + m->rc.capacity = 0; +- p9_req_put(m->rreq); ++ p9_req_put(m->client, m->rreq); + m->rreq = NULL; + } + +@@ -494,7 +495,7 @@ static void p9_write_work(struct work_struct *work) + m->wpos += err; + if (m->wpos == m->wsize) { + m->wpos = m->wsize = 0; +- p9_req_put(m->wreq); ++ p9_req_put(m->client, m->wreq); + m->wreq = NULL; + } + +@@ -697,7 +698,7 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req) + if (req->status == REQ_STATUS_UNSENT) { + list_del(&req->req_list); + req->status = REQ_STATUS_FLSHD; +- p9_req_put(req); ++ p9_req_put(client, req); + ret = 0; + } + spin_unlock(&client->lock); +@@ -724,7 +725,7 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req) + list_del(&req->req_list); + req->status = REQ_STATUS_FLSHD; + spin_unlock(&client->lock); +- p9_req_put(req); ++ p9_req_put(client, req); + + return 0; + } +@@ -885,12 +886,12 @@ static void p9_conn_destroy(struct p9_conn *m) + p9_mux_poll_stop(m); + cancel_work_sync(&m->rq); + if (m->rreq) { +- p9_req_put(m->rreq); ++ p9_req_put(m->client, m->rreq); + m->rreq = NULL; + } + cancel_work_sync(&m->wq); + if (m->wreq) { +- p9_req_put(m->wreq); ++ p9_req_put(m->client, m->wreq); + m->wreq = NULL; + } + +diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c +index af0a8a6cd3fd8..f6d145873b497 100644 +--- a/net/9p/trans_rdma.c ++++ b/net/9p/trans_rdma.c +@@ -352,7 +352,7 @@ send_done(struct ib_cq *cq, struct ib_wc *wc) + c->busa, c->req->tc.size, + DMA_TO_DEVICE); + up(&rdma->sq_sem); +- p9_req_put(c->req); ++ p9_req_put(client, c->req); + kfree(c); + } + +diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c +index 490a4c9003395..d110df3cb4e1d 100644 +--- a/net/9p/trans_virtio.c ++++ b/net/9p/trans_virtio.c +@@ -199,7 +199,7 @@ static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req) + /* Reply won't come, so drop req ref */ + static int p9_virtio_cancelled(struct p9_client *client, struct p9_req_t *req) + { +- p9_req_put(req); ++ p9_req_put(client, req); + return 0; + } + +@@ -523,7 +523,7 @@ err_out: + kvfree(out_pages); + if (!kicked) { + /* reply won't come */ +- p9_req_put(req); ++ p9_req_put(client, req); + } + return err; + } +diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c +index 432ac5a16f2e0..427f6caefa29f 100644 +--- a/net/9p/trans_xen.c ++++ b/net/9p/trans_xen.c +@@ -186,7 +186,7 @@ again: + ring->intf->out_prod = prod; + spin_unlock_irqrestore(&ring->lock, flags); + notify_remote_via_irq(ring->irq); +- p9_req_put(p9_req); ++ p9_req_put(client, p9_req); + + return 0; + } +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 780073f6affcb..a0e0c2bdbb49a 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -1970,11 +1970,11 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, + bdaddr_t *dst, + u8 link_type) + { +- struct l2cap_chan *c, *c1 = NULL; ++ struct l2cap_chan *c, *tmp, *c1 = NULL; + + read_lock(&chan_list_lock); + +- list_for_each_entry(c, &chan_list, global_l) { ++ list_for_each_entry_safe(c, tmp, &chan_list, global_l) { + if (state && c->state != state) + continue; + +@@ -1993,11 +1993,10 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, + dst_match = !bacmp(&c->dst, dst); + if (src_match && dst_match) { + c = l2cap_chan_hold_unless_zero(c); +- if (!c) +- continue; +- +- read_unlock(&chan_list_lock); +- return c; ++ if (c) { ++ read_unlock(&chan_list_lock); ++ return c; ++ } + } + + /* Closest match */ +diff --git a/net/core/skmsg.c b/net/core/skmsg.c +index ede0af308f404..f50f8d95b6283 100644 +--- a/net/core/skmsg.c ++++ b/net/core/skmsg.c +@@ -462,7 +462,7 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg, + + if (copied == len) + break; +- } while (i != msg_rx->sg.end); ++ } while (!sg_is_last(sge)); + + if (unlikely(peek)) { + msg_rx = sk_psock_next_msg(psock, msg_rx); +@@ -472,7 +472,7 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg, + } + + msg_rx->sg.start = i; +- if (!sge->length && msg_rx->sg.start == msg_rx->sg.end) { ++ if (!sge->length && sg_is_last(sge)) { + msg_rx = sk_psock_dequeue_msg(psock); + kfree_sk_msg(msg_rx); + } +diff --git a/net/dccp/proto.c b/net/dccp/proto.c +index fc44dadc778bb..c4de716f4994a 100644 +--- a/net/dccp/proto.c ++++ b/net/dccp/proto.c +@@ -747,11 +747,6 @@ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + + lock_sock(sk); + +- if (dccp_qpolicy_full(sk)) { +- rc = -EAGAIN; +- goto out_release; +- } +- + timeo = sock_sndtimeo(sk, noblock); + + /* +@@ -770,6 +765,11 @@ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + if (skb == NULL) + goto out_release; + ++ if (dccp_qpolicy_full(sk)) { ++ rc = -EAGAIN; ++ goto out_discard; ++ } ++ + if (sk->sk_state == DCCP_CLOSED) { + rc = -ENOTCONN; + goto out_discard; +diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c +index 342f3df778359..26c4dd4ec459b 100644 +--- a/net/ipv4/inet_hashtables.c ++++ b/net/ipv4/inet_hashtables.c +@@ -410,13 +410,11 @@ begin: + sk_nulls_for_each_rcu(sk, node, &head->chain) { + if (sk->sk_hash != hash) + continue; +- if (likely(INET_MATCH(sk, net, acookie, +- saddr, daddr, ports, dif, sdif))) { ++ if (likely(INET_MATCH(net, sk, acookie, ports, dif, sdif))) { + if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt))) + goto out; +- if (unlikely(!INET_MATCH(sk, net, acookie, +- saddr, daddr, ports, +- dif, sdif))) { ++ if (unlikely(!INET_MATCH(net, sk, acookie, ++ ports, dif, sdif))) { + sock_gen_put(sk); + goto begin; + } +@@ -465,8 +463,7 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row, + if (sk2->sk_hash != hash) + continue; + +- if (likely(INET_MATCH(sk2, net, acookie, +- saddr, daddr, ports, dif, sdif))) { ++ if (likely(INET_MATCH(net, sk2, acookie, ports, dif, sdif))) { + if (sk2->sk_state == TCP_TIME_WAIT) { + tw = inet_twsk(sk2); + if (twsk_unique(sk, sk2, twp)) +@@ -532,16 +529,14 @@ static bool inet_ehash_lookup_by_sk(struct sock *sk, + if (esk->sk_hash != sk->sk_hash) + continue; + if (sk->sk_family == AF_INET) { +- if (unlikely(INET_MATCH(esk, net, acookie, +- sk->sk_daddr, +- sk->sk_rcv_saddr, ++ if (unlikely(INET_MATCH(net, esk, acookie, + ports, dif, sdif))) { + return true; + } + } + #if IS_ENABLED(CONFIG_IPV6) + else if (sk->sk_family == AF_INET6) { +- if (unlikely(INET6_MATCH(esk, net, ++ if (unlikely(inet6_match(net, esk, + &sk->sk_v6_daddr, + &sk->sk_v6_rcv_saddr, + ports, dif, sdif))) { +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 9c9a0f7a3deea..40c9da4bd03e4 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -3145,7 +3145,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs) + struct tcp_sock *tp = tcp_sk(sk); + unsigned int cur_mss; + int diff, len, err; +- ++ int avail_wnd; + + /* Inconclusive MTU probe */ + if (icsk->icsk_mtup.probe_size) +@@ -3167,17 +3167,25 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs) + return -EHOSTUNREACH; /* Routing failure or similar. */ + + cur_mss = tcp_current_mss(sk); ++ avail_wnd = tcp_wnd_end(tp) - TCP_SKB_CB(skb)->seq; + + /* If receiver has shrunk his window, and skb is out of + * new window, do not retransmit it. The exception is the + * case, when window is shrunk to zero. In this case +- * our retransmit serves as a zero window probe. ++ * our retransmit of one segment serves as a zero window probe. + */ +- if (!before(TCP_SKB_CB(skb)->seq, tcp_wnd_end(tp)) && +- TCP_SKB_CB(skb)->seq != tp->snd_una) +- return -EAGAIN; ++ if (avail_wnd <= 0) { ++ if (TCP_SKB_CB(skb)->seq != tp->snd_una) ++ return -EAGAIN; ++ avail_wnd = cur_mss; ++ } + + len = cur_mss * segs; ++ if (len > avail_wnd) { ++ len = rounddown(avail_wnd, cur_mss); ++ if (!len) ++ len = avail_wnd; ++ } + if (skb->len > len) { + if (tcp_fragment(sk, TCP_FRAG_IN_RTX_QUEUE, skb, len, + cur_mss, GFP_ATOMIC)) +@@ -3191,8 +3199,9 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs) + diff -= tcp_skb_pcount(skb); + if (diff) + tcp_adjust_pcount(sk, skb, diff); +- if (skb->len < cur_mss) +- tcp_retrans_try_collapse(sk, skb, cur_mss); ++ avail_wnd = min_t(int, avail_wnd, cur_mss); ++ if (skb->len < avail_wnd) ++ tcp_retrans_try_collapse(sk, skb, avail_wnd); + } + + /* RFC3168, section 6.1.1.1. ECN fallback */ +@@ -3363,11 +3372,12 @@ void tcp_xmit_retransmit_queue(struct sock *sk) + */ + void sk_forced_mem_schedule(struct sock *sk, int size) + { +- int amt; ++ int delta, amt; + +- if (size <= sk->sk_forward_alloc) ++ delta = size - sk->sk_forward_alloc; ++ if (delta <= 0) + return; +- amt = sk_mem_pages(size); ++ amt = sk_mem_pages(delta); + sk->sk_forward_alloc += amt * SK_MEM_QUANTUM; + sk_memory_allocated_add(sk, amt); + +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index 4ad4daa16cce5..efef7ba44e1d6 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -2554,8 +2554,7 @@ static struct sock *__udp4_lib_demux_lookup(struct net *net, + struct sock *sk; + + udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) { +- if (INET_MATCH(sk, net, acookie, rmt_addr, +- loc_addr, ports, dif, sdif)) ++ if (INET_MATCH(net, sk, acookie, ports, dif, sdif)) + return sk; + /* Only check first socket in chain */ + break; +diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c +index 40203255ed88b..b4a5e01e12016 100644 +--- a/net/ipv6/inet6_hashtables.c ++++ b/net/ipv6/inet6_hashtables.c +@@ -71,12 +71,12 @@ begin: + sk_nulls_for_each_rcu(sk, node, &head->chain) { + if (sk->sk_hash != hash) + continue; +- if (!INET6_MATCH(sk, net, saddr, daddr, ports, dif, sdif)) ++ if (!inet6_match(net, sk, saddr, daddr, ports, dif, sdif)) + continue; + if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt))) + goto out; + +- if (unlikely(!INET6_MATCH(sk, net, saddr, daddr, ports, dif, sdif))) { ++ if (unlikely(!inet6_match(net, sk, saddr, daddr, ports, dif, sdif))) { + sock_gen_put(sk); + goto begin; + } +@@ -269,7 +269,7 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row, + if (sk2->sk_hash != hash) + continue; + +- if (likely(INET6_MATCH(sk2, net, saddr, daddr, ports, ++ if (likely(inet6_match(net, sk2, saddr, daddr, ports, + dif, sdif))) { + if (sk2->sk_state == TCP_TIME_WAIT) { + tw = inet_twsk(sk2); +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index 932c6f2a54946..4a9afdbd5f292 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -1035,7 +1035,7 @@ static struct sock *__udp6_lib_demux_lookup(struct net *net, + + udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) { + if (sk->sk_state == TCP_ESTABLISHED && +- INET6_MATCH(sk, net, rmt_addr, loc_addr, ports, dif, sdif)) ++ inet6_match(net, sk, rmt_addr, loc_addr, ports, dif, sdif)) + return sk; + /* Only check first socket in chain */ + break; +diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c +index ef729b1e39ea3..e43176794149b 100644 +--- a/net/mac80211/agg-rx.c ++++ b/net/mac80211/agg-rx.c +@@ -310,7 +310,7 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta, + } + + if (sta->sta.he_cap.has_he) +- max_buf_size = IEEE80211_MAX_AMPDU_BUF; ++ max_buf_size = IEEE80211_MAX_AMPDU_BUF_HE; + else + max_buf_size = IEEE80211_MAX_AMPDU_BUF_HT; + +diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c +index 2b5acb37587f7..6eeef7a61927b 100644 +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -641,13 +641,13 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) + /* check if STA exists already */ + if (sta_info_get_bss(sdata, sta->sta.addr)) { + err = -EEXIST; +- goto out_err; ++ goto out_cleanup; + } + + sinfo = kzalloc(sizeof(struct station_info), GFP_KERNEL); + if (!sinfo) { + err = -ENOMEM; +- goto out_err; ++ goto out_cleanup; + } + + local->num_sta++; +@@ -703,8 +703,8 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) + out_drop_sta: + local->num_sta--; + synchronize_net(); ++ out_cleanup: + cleanup_single_sta(sta); +- out_err: + mutex_unlock(&local->sta_mtx); + kfree(sinfo); + rcu_read_lock(); +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index a32acf056e326..13d14fcc23712 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -153,6 +153,7 @@ static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx, + if (trans == NULL) + return NULL; + ++ INIT_LIST_HEAD(&trans->list); + trans->msg_type = msg_type; + trans->ctx = *ctx; + +@@ -2377,6 +2378,7 @@ err: + } + + static struct nft_chain *nft_chain_lookup_byid(const struct net *net, ++ const struct nft_table *table, + const struct nlattr *nla) + { + struct nftables_pernet *nft_net = nft_pernet(net); +@@ -2387,6 +2389,7 @@ static struct nft_chain *nft_chain_lookup_byid(const struct net *net, + struct nft_chain *chain = trans->ctx.chain; + + if (trans->msg_type == NFT_MSG_NEWCHAIN && ++ chain->table == table && + id == nft_trans_chain_id(trans)) + return chain; + } +@@ -3274,6 +3277,7 @@ static int nft_table_validate(struct net *net, const struct nft_table *table) + } + + static struct nft_rule *nft_rule_lookup_byid(const struct net *net, ++ const struct nft_chain *chain, + const struct nlattr *nla); + + #define NFT_RULE_MAXEXPRS 128 +@@ -3320,7 +3324,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info, + return -EOPNOTSUPP; + + } else if (nla[NFTA_RULE_CHAIN_ID]) { +- chain = nft_chain_lookup_byid(net, nla[NFTA_RULE_CHAIN_ID]); ++ chain = nft_chain_lookup_byid(net, table, nla[NFTA_RULE_CHAIN_ID]); + if (IS_ERR(chain)) { + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN_ID]); + return PTR_ERR(chain); +@@ -3362,7 +3366,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info, + return PTR_ERR(old_rule); + } + } else if (nla[NFTA_RULE_POSITION_ID]) { +- old_rule = nft_rule_lookup_byid(net, nla[NFTA_RULE_POSITION_ID]); ++ old_rule = nft_rule_lookup_byid(net, chain, nla[NFTA_RULE_POSITION_ID]); + if (IS_ERR(old_rule)) { + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_POSITION_ID]); + return PTR_ERR(old_rule); +@@ -3507,6 +3511,7 @@ err_release_expr: + } + + static struct nft_rule *nft_rule_lookup_byid(const struct net *net, ++ const struct nft_chain *chain, + const struct nlattr *nla) + { + struct nftables_pernet *nft_net = nft_pernet(net); +@@ -3517,6 +3522,7 @@ static struct nft_rule *nft_rule_lookup_byid(const struct net *net, + struct nft_rule *rule = nft_trans_rule(trans); + + if (trans->msg_type == NFT_MSG_NEWRULE && ++ trans->ctx.chain == chain && + id == nft_trans_rule_id(trans)) + return rule; + } +@@ -3566,7 +3572,7 @@ static int nf_tables_delrule(struct sk_buff *skb, const struct nfnl_info *info, + + err = nft_delrule(&ctx, rule); + } else if (nla[NFTA_RULE_ID]) { +- rule = nft_rule_lookup_byid(net, nla[NFTA_RULE_ID]); ++ rule = nft_rule_lookup_byid(net, chain, nla[NFTA_RULE_ID]); + if (IS_ERR(rule)) { + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_ID]); + return PTR_ERR(rule); +@@ -3745,6 +3751,7 @@ static struct nft_set *nft_set_lookup_byhandle(const struct nft_table *table, + } + + static struct nft_set *nft_set_lookup_byid(const struct net *net, ++ const struct nft_table *table, + const struct nlattr *nla, u8 genmask) + { + struct nftables_pernet *nft_net = nft_pernet(net); +@@ -3756,6 +3763,7 @@ static struct nft_set *nft_set_lookup_byid(const struct net *net, + struct nft_set *set = nft_trans_set(trans); + + if (id == nft_trans_set_id(trans) && ++ set->table == table && + nft_active_genmask(set, genmask)) + return set; + } +@@ -3776,7 +3784,7 @@ struct nft_set *nft_set_lookup_global(const struct net *net, + if (!nla_set_id) + return set; + +- set = nft_set_lookup_byid(net, nla_set_id, genmask); ++ set = nft_set_lookup_byid(net, table, nla_set_id, genmask); + } + return set; + } +@@ -9449,7 +9457,7 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data, + tb[NFTA_VERDICT_CHAIN], + genmask); + } else if (tb[NFTA_VERDICT_CHAIN_ID]) { +- chain = nft_chain_lookup_byid(ctx->net, ++ chain = nft_chain_lookup_byid(ctx->net, ctx->table, + tb[NFTA_VERDICT_CHAIN_ID]); + if (IS_ERR(chain)) + return PTR_ERR(chain); +diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c +index cf7d974e0f619..29a208ed8fb88 100644 +--- a/net/rose/af_rose.c ++++ b/net/rose/af_rose.c +@@ -191,6 +191,7 @@ static void rose_kill_by_device(struct net_device *dev) + rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); + if (rose->neighbour) + rose->neighbour->use--; ++ dev_put(rose->device); + rose->device = NULL; + } + } +@@ -591,6 +592,8 @@ static struct sock *rose_make_new(struct sock *osk) + rose->idle = orose->idle; + rose->defer = orose->defer; + rose->device = orose->device; ++ if (rose->device) ++ dev_hold(rose->device); + rose->qbitincl = orose->qbitincl; + + return sk; +@@ -644,6 +647,7 @@ static int rose_release(struct socket *sock) + break; + } + ++ dev_put(rose->device); + sock->sk = NULL; + release_sock(sk); + sock_put(sk); +@@ -720,7 +724,6 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le + struct rose_sock *rose = rose_sk(sk); + struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr; + unsigned char cause, diagnostic; +- struct net_device *dev; + ax25_uid_assoc *user; + int n, err = 0; + +@@ -777,9 +780,12 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le + } + + if (sock_flag(sk, SOCK_ZAPPED)) { /* Must bind first - autobinding in this may or may not work */ ++ struct net_device *dev; ++ + sock_reset_flag(sk, SOCK_ZAPPED); + +- if ((dev = rose_dev_first()) == NULL) { ++ dev = rose_dev_first(); ++ if (!dev) { + err = -ENETUNREACH; + goto out_release; + } +@@ -787,6 +793,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le + user = ax25_findbyuid(current_euid()); + if (!user) { + err = -EINVAL; ++ dev_put(dev); + goto out_release; + } + +diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c +index 764a726debb1f..66aa05db5390f 100644 +--- a/net/rose/rose_route.c ++++ b/net/rose/rose_route.c +@@ -615,6 +615,8 @@ struct net_device *rose_dev_first(void) + if (first == NULL || strncmp(dev->name, first->name, 3) < 0) + first = dev; + } ++ if (first) ++ dev_hold(first); + rcu_read_unlock(); + + return first; +diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c +index a35ab8c27866e..3f935cbbaff66 100644 +--- a/net/sched/cls_route.c ++++ b/net/sched/cls_route.c +@@ -526,7 +526,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb, + rcu_assign_pointer(f->next, f1); + rcu_assign_pointer(*fp, f); + +- if (fold && fold->handle && f->handle != fold->handle) { ++ if (fold) { + th = to_hash(fold->handle); + h = from_hash(fold->handle >> 16); + b = rtnl_dereference(head->table[th]); +diff --git a/scripts/faddr2line b/scripts/faddr2line +index 94ed98dd899f3..57099687e5e1d 100755 +--- a/scripts/faddr2line ++++ b/scripts/faddr2line +@@ -112,7 +112,9 @@ __faddr2line() { + # section offsets. + local file_type=$(${READELF} --file-header $objfile | + ${AWK} '$1 == "Type:" { print $2; exit }') +- [[ $file_type = "EXEC" ]] && is_vmlinux=1 ++ if [[ $file_type = "EXEC" ]] || [[ $file_type == "DYN" ]]; then ++ is_vmlinux=1 ++ fi + + # Go through each of the object's symbols which match the func name. + # In rare cases there might be duplicates, in which case we print all +diff --git a/scripts/gdb/linux/dmesg.py b/scripts/gdb/linux/dmesg.py +index a92c55bd8de54..c771831eb077d 100644 +--- a/scripts/gdb/linux/dmesg.py ++++ b/scripts/gdb/linux/dmesg.py +@@ -22,7 +22,6 @@ prb_desc_type = utils.CachedType("struct prb_desc") + prb_desc_ring_type = utils.CachedType("struct prb_desc_ring") + prb_data_ring_type = utils.CachedType("struct prb_data_ring") + printk_ringbuffer_type = utils.CachedType("struct printk_ringbuffer") +-atomic_long_type = utils.CachedType("atomic_long_t") + + class LxDmesg(gdb.Command): + """Print Linux kernel log buffer.""" +@@ -44,19 +43,17 @@ class LxDmesg(gdb.Command): + sz = prb_desc_ring_type.get_type().sizeof + desc_ring = utils.read_memoryview(inf, addr, sz).tobytes() + +- # read in descriptor array ++ # read in descriptor count, size, and address + off = prb_desc_ring_type.get_type()['count_bits'].bitpos // 8 + desc_ring_count = 1 << utils.read_u32(desc_ring, off) + desc_sz = prb_desc_type.get_type().sizeof + off = prb_desc_ring_type.get_type()['descs'].bitpos // 8 +- addr = utils.read_ulong(desc_ring, off) +- descs = utils.read_memoryview(inf, addr, desc_sz * desc_ring_count).tobytes() ++ desc_addr = utils.read_ulong(desc_ring, off) + +- # read in info array ++ # read in info size and address + info_sz = printk_info_type.get_type().sizeof + off = prb_desc_ring_type.get_type()['infos'].bitpos // 8 +- addr = utils.read_ulong(desc_ring, off) +- infos = utils.read_memoryview(inf, addr, info_sz * desc_ring_count).tobytes() ++ info_addr = utils.read_ulong(desc_ring, off) + + # read in text data ring structure + off = printk_ringbuffer_type.get_type()['text_data_ring'].bitpos // 8 +@@ -64,14 +61,11 @@ class LxDmesg(gdb.Command): + sz = prb_data_ring_type.get_type().sizeof + text_data_ring = utils.read_memoryview(inf, addr, sz).tobytes() + +- # read in text data ++ # read in text data size and address + off = prb_data_ring_type.get_type()['size_bits'].bitpos // 8 + text_data_sz = 1 << utils.read_u32(text_data_ring, off) + off = prb_data_ring_type.get_type()['data'].bitpos // 8 +- addr = utils.read_ulong(text_data_ring, off) +- text_data = utils.read_memoryview(inf, addr, text_data_sz).tobytes() +- +- counter_off = atomic_long_type.get_type()['counter'].bitpos // 8 ++ text_data_addr = utils.read_ulong(text_data_ring, off) + + sv_off = prb_desc_type.get_type()['state_var'].bitpos // 8 + +@@ -92,9 +86,9 @@ class LxDmesg(gdb.Command): + + # read in tail and head descriptor ids + off = prb_desc_ring_type.get_type()['tail_id'].bitpos // 8 +- tail_id = utils.read_u64(desc_ring, off + counter_off) ++ tail_id = utils.read_atomic_long(desc_ring, off) + off = prb_desc_ring_type.get_type()['head_id'].bitpos // 8 +- head_id = utils.read_u64(desc_ring, off + counter_off) ++ head_id = utils.read_atomic_long(desc_ring, off) + + did = tail_id + while True: +@@ -102,17 +96,20 @@ class LxDmesg(gdb.Command): + desc_off = desc_sz * ind + info_off = info_sz * ind + ++ desc = utils.read_memoryview(inf, desc_addr + desc_off, desc_sz).tobytes() ++ + # skip non-committed record +- state = 3 & (utils.read_u64(descs, desc_off + sv_off + +- counter_off) >> desc_flags_shift) ++ state = 3 & (utils.read_atomic_long(desc, sv_off) >> desc_flags_shift) + if state != desc_committed and state != desc_finalized: + if did == head_id: + break + did = (did + 1) & desc_id_mask + continue + +- begin = utils.read_ulong(descs, desc_off + begin_off) % text_data_sz +- end = utils.read_ulong(descs, desc_off + next_off) % text_data_sz ++ begin = utils.read_ulong(desc, begin_off) % text_data_sz ++ end = utils.read_ulong(desc, next_off) % text_data_sz ++ ++ info = utils.read_memoryview(inf, info_addr + info_off, info_sz).tobytes() + + # handle data-less record + if begin & 1 == 1: +@@ -125,16 +122,17 @@ class LxDmesg(gdb.Command): + # skip over descriptor id + text_start = begin + utils.get_long_type().sizeof + +- text_len = utils.read_u16(infos, info_off + len_off) ++ text_len = utils.read_u16(info, len_off) + + # handle truncated message + if end - text_start < text_len: + text_len = end - text_start + +- text = text_data[text_start:text_start + text_len].decode( +- encoding='utf8', errors='replace') ++ text_data = utils.read_memoryview(inf, text_data_addr + text_start, ++ text_len).tobytes() ++ text = text_data[0:text_len].decode(encoding='utf8', errors='replace') + +- time_stamp = utils.read_u64(infos, info_off + ts_off) ++ time_stamp = utils.read_u64(info, ts_off) + + for line in text.splitlines(): + msg = u"[{time:12.6f}] {line}\n".format( +diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py +index ff7c1799d588f..1553f68716cc2 100644 +--- a/scripts/gdb/linux/utils.py ++++ b/scripts/gdb/linux/utils.py +@@ -35,13 +35,12 @@ class CachedType: + + + long_type = CachedType("long") +- ++atomic_long_type = CachedType("atomic_long_t") + + def get_long_type(): + global long_type + return long_type.get_type() + +- + def offset_of(typeobj, field): + element = gdb.Value(0).cast(typeobj) + return int(str(element[field].address).split()[0], 16) +@@ -129,6 +128,17 @@ def read_ulong(buffer, offset): + else: + return read_u32(buffer, offset) + ++atomic_long_counter_offset = atomic_long_type.get_type()['counter'].bitpos ++atomic_long_counter_sizeof = atomic_long_type.get_type()['counter'].type.sizeof ++ ++def read_atomic_long(buffer, offset): ++ global atomic_long_counter_offset ++ global atomic_long_counter_sizeof ++ ++ if atomic_long_counter_sizeof == 8: ++ return read_u64(buffer, offset + atomic_long_counter_offset) ++ else: ++ return read_u32(buffer, offset + atomic_long_counter_offset) + + target_arch = None + +diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h +index c24d4e1063ea0..ffc4e7bad2054 100644 +--- a/security/selinux/ss/policydb.h ++++ b/security/selinux/ss/policydb.h +@@ -370,6 +370,8 @@ static inline int put_entry(const void *buf, size_t bytes, int num, struct polic + { + size_t len = bytes * num; + ++ if (len > fp->len) ++ return -EINVAL; + memcpy(fp->data, buf, len); + fp->data += len; + fp->len -= len; +diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c +index c4931bf6f92a4..e8035e4876df0 100644 +--- a/security/selinux/ss/services.c ++++ b/security/selinux/ss/services.c +@@ -4045,6 +4045,7 @@ int security_read_policy(struct selinux_state *state, + int security_read_state_kernel(struct selinux_state *state, + void **data, size_t *len) + { ++ int err; + struct selinux_policy *policy; + + policy = rcu_dereference_protected( +@@ -4057,5 +4058,11 @@ int security_read_state_kernel(struct selinux_state *state, + if (!*data) + return -ENOMEM; + +- return __security_read_policy(policy, *data, len); ++ err = __security_read_policy(policy, *data, len); ++ if (err) { ++ vfree(*data); ++ *data = NULL; ++ *len = 0; ++ } ++ return err; + } +diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c +index 678fbcaf2a3bc..6807b4708a176 100644 +--- a/sound/pci/hda/patch_cirrus.c ++++ b/sound/pci/hda/patch_cirrus.c +@@ -395,6 +395,7 @@ static const struct snd_pci_quirk cs420x_fixup_tbl[] = { + + /* codec SSID */ + SND_PCI_QUIRK(0x106b, 0x0600, "iMac 14,1", CS420X_IMAC27_122), ++ SND_PCI_QUIRK(0x106b, 0x0900, "iMac 12,1", CS420X_IMAC27_122), + SND_PCI_QUIRK(0x106b, 0x1c00, "MacBookPro 8,1", CS420X_MBP81), + SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122), + SND_PCI_QUIRK(0x106b, 0x2800, "MacBookPro 10,1", CS420X_MBP101), +diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c +index 8c68e6e1387ef..2bc9274e0960b 100644 +--- a/sound/pci/hda/patch_conexant.c ++++ b/sound/pci/hda/patch_conexant.c +@@ -222,6 +222,7 @@ enum { + CXT_PINCFG_LEMOTE_A1205, + CXT_PINCFG_COMPAQ_CQ60, + CXT_FIXUP_STEREO_DMIC, ++ CXT_PINCFG_LENOVO_NOTEBOOK, + CXT_FIXUP_INC_MIC_BOOST, + CXT_FIXUP_HEADPHONE_MIC_PIN, + CXT_FIXUP_HEADPHONE_MIC, +@@ -772,6 +773,14 @@ static const struct hda_fixup cxt_fixups[] = { + .type = HDA_FIXUP_FUNC, + .v.func = cxt_fixup_stereo_dmic, + }, ++ [CXT_PINCFG_LENOVO_NOTEBOOK] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x1a, 0x05d71030 }, ++ { } ++ }, ++ .chain_id = CXT_FIXUP_STEREO_DMIC, ++ }, + [CXT_FIXUP_INC_MIC_BOOST] = { + .type = HDA_FIXUP_FUNC, + .v.func = cxt5066_increase_mic_boost, +@@ -971,7 +980,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { + SND_PCI_QUIRK(0x17aa, 0x3905, "Lenovo G50-30", CXT_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x17aa, 0x390b, "Lenovo G50-80", CXT_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC), +- SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC), ++ SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_PINCFG_LENOVO_NOTEBOOK), + SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo G50-70", CXT_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", CXT_FIXUP_THINKPAD_ACPI), +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index f3fa35b302ce9..f7ab620d0e300 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -6721,6 +6721,7 @@ enum { + ALC269_FIXUP_LIMIT_INT_MIC_BOOST, + ALC269VB_FIXUP_ASUS_ZENBOOK, + ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A, ++ ALC269VB_FIXUP_ASUS_MIC_NO_PRESENCE, + ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED, + ALC269VB_FIXUP_ORDISSIMO_EVE2, + ALC283_FIXUP_CHROME_BOOK, +@@ -7297,6 +7298,15 @@ static const struct hda_fixup alc269_fixups[] = { + .chained = true, + .chain_id = ALC269VB_FIXUP_ASUS_ZENBOOK, + }, ++ [ALC269VB_FIXUP_ASUS_MIC_NO_PRESENCE] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x18, 0x01a110f0 }, /* use as headset mic */ ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC269_FIXUP_HEADSET_MIC ++ }, + [ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc269_fixup_limit_int_mic_boost, +@@ -8852,6 +8862,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x861f, "HP Elite Dragonfly G1", ALC285_FIXUP_HP_GPIO_AMP_INIT), + SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO), ++ SND_PCI_QUIRK(0x103c, 0x86e7, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1), ++ SND_PCI_QUIRK(0x103c, 0x86e8, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1), + SND_PCI_QUIRK(0x103c, 0x8716, "HP Elite Dragonfly G2 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), + SND_PCI_QUIRK(0x103c, 0x8720, "HP EliteBook x360 1040 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), + SND_PCI_QUIRK(0x103c, 0x8724, "HP EliteBook 850 G7", ALC285_FIXUP_HP_GPIO_LED), +@@ -8867,6 +8879,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + ALC285_FIXUP_HP_GPIO_AMP_INIT), + SND_PCI_QUIRK(0x103c, 0x8783, "HP ZBook Fury 15 G7 Mobile Workstation", + ALC285_FIXUP_HP_GPIO_AMP_INIT), ++ SND_PCI_QUIRK(0x103c, 0x8786, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x8787, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x8788, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED), +@@ -8917,6 +8930,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1043, 0x12a0, "ASUS X441UV", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1043, 0x12e0, "ASUS X541SA", ALC256_FIXUP_ASUS_MIC), + SND_PCI_QUIRK(0x1043, 0x12f0, "ASUS X541UV", ALC256_FIXUP_ASUS_MIC), ++ SND_PCI_QUIRK(0x1043, 0x1313, "Asus K42JZ", ALC269VB_FIXUP_ASUS_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC), + SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK), + SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A), +@@ -8992,6 +9006,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1558, 0x4018, "Clevo NV40M[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x4019, "Clevo NV40MZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x4020, "Clevo NV40MB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), ++ SND_PCI_QUIRK(0x1558, 0x4041, "Clevo NV4[15]PZ", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x40a1, "Clevo NL40GU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x40c1, "Clevo NL40[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x40d1, "Clevo NL41DU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), +diff --git a/sound/soc/atmel/mchp-spdifrx.c b/sound/soc/atmel/mchp-spdifrx.c +index bcd4f3e4fb0fb..2a62d9a2fa0d0 100644 +--- a/sound/soc/atmel/mchp-spdifrx.c ++++ b/sound/soc/atmel/mchp-spdifrx.c +@@ -288,15 +288,17 @@ static void mchp_spdifrx_isr_blockend_en(struct mchp_spdifrx_dev *dev) + spin_unlock_irqrestore(&dev->blockend_lock, flags); + } + +-/* called from atomic context only */ ++/* called from atomic/non-atomic context */ + static void mchp_spdifrx_isr_blockend_dis(struct mchp_spdifrx_dev *dev) + { +- spin_lock(&dev->blockend_lock); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dev->blockend_lock, flags); + dev->blockend_refcount--; + /* don't enable BLOCKEND interrupt if it's already enabled */ + if (dev->blockend_refcount == 0) + regmap_write(dev->regmap, SPDIFRX_IDR, SPDIFRX_IR_BLOCKEND); +- spin_unlock(&dev->blockend_lock); ++ spin_unlock_irqrestore(&dev->blockend_lock, flags); + } + + static irqreturn_t mchp_spdif_interrupt(int irq, void *dev_id) +@@ -575,6 +577,7 @@ static int mchp_spdifrx_subcode_ch_get(struct mchp_spdifrx_dev *dev, + if (ret <= 0) { + dev_dbg(dev->dev, "user data for channel %d timeout\n", + channel); ++ mchp_spdifrx_isr_blockend_dis(dev); + return ret; + } + +diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c +index a201d652aca2b..8823edc351130 100644 +--- a/sound/soc/codecs/cros_ec_codec.c ++++ b/sound/soc/codecs/cros_ec_codec.c +@@ -994,6 +994,7 @@ static int cros_ec_codec_platform_probe(struct platform_device *pdev) + dev_dbg(dev, "ap_shm_phys_addr=%#llx len=%#x\n", + priv->ap_shm_phys_addr, priv->ap_shm_len); + } ++ of_node_put(node); + } + #endif + +diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c +index 8af344b2fdbf6..d75d15006f64e 100644 +--- a/sound/soc/codecs/da7210.c ++++ b/sound/soc/codecs/da7210.c +@@ -1336,6 +1336,8 @@ static int __init da7210_modinit(void) + int ret = 0; + #if IS_ENABLED(CONFIG_I2C) + ret = i2c_add_driver(&da7210_i2c_driver); ++ if (ret) ++ return ret; + #endif + #if defined(CONFIG_SPI_MASTER) + ret = spi_register_driver(&da7210_spi_driver); +diff --git a/sound/soc/codecs/msm8916-wcd-digital.c b/sound/soc/codecs/msm8916-wcd-digital.c +index 20a07c92b2fc2..098a58990f07d 100644 +--- a/sound/soc/codecs/msm8916-wcd-digital.c ++++ b/sound/soc/codecs/msm8916-wcd-digital.c +@@ -328,8 +328,8 @@ static const struct snd_kcontrol_new rx1_mix2_inp1_mux = SOC_DAPM_ENUM( + static const struct snd_kcontrol_new rx2_mix2_inp1_mux = SOC_DAPM_ENUM( + "RX2 MIX2 INP1 Mux", rx2_mix2_inp1_chain_enum); + +-/* Digital Gain control -38.4 dB to +38.4 dB in 0.3 dB steps */ +-static const DECLARE_TLV_DB_SCALE(digital_gain, -3840, 30, 0); ++/* Digital Gain control -84 dB to +40 dB in 1 dB steps */ ++static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400); + + /* Cutoff Freq for High Pass Filter at -3dB */ + static const char * const hpf_cutoff_text[] = { +@@ -510,15 +510,15 @@ static int wcd_iir_filter_info(struct snd_kcontrol *kcontrol, + + static const struct snd_kcontrol_new msm8916_wcd_digital_snd_controls[] = { + SOC_SINGLE_S8_TLV("RX1 Digital Volume", LPASS_CDC_RX1_VOL_CTL_B2_CTL, +- -128, 127, digital_gain), ++ -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX2 Digital Volume", LPASS_CDC_RX2_VOL_CTL_B2_CTL, +- -128, 127, digital_gain), ++ -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX3 Digital Volume", LPASS_CDC_RX3_VOL_CTL_B2_CTL, +- -128, 127, digital_gain), ++ -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX1 Digital Volume", LPASS_CDC_TX1_VOL_CTL_GAIN, +- -128, 127, digital_gain), ++ -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX2 Digital Volume", LPASS_CDC_TX2_VOL_CTL_GAIN, +- -128, 127, digital_gain), ++ -84, 40, digital_gain), + SOC_ENUM("TX1 HPF Cutoff", tx1_hpf_cutoff_enum), + SOC_ENUM("TX2 HPF Cutoff", tx2_hpf_cutoff_enum), + SOC_SINGLE("TX1 HPF Switch", LPASS_CDC_TX1_MUX_CTL, 3, 1, 0), +@@ -553,22 +553,22 @@ static const struct snd_kcontrol_new msm8916_wcd_digital_snd_controls[] = { + WCD_IIR_FILTER_CTL("IIR2 Band3", IIR2, BAND3), + WCD_IIR_FILTER_CTL("IIR2 Band4", IIR2, BAND4), + WCD_IIR_FILTER_CTL("IIR2 Band5", IIR2, BAND5), +- SOC_SINGLE_SX_TLV("IIR1 INP1 Volume", LPASS_CDC_IIR1_GAIN_B1_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("IIR1 INP2 Volume", LPASS_CDC_IIR1_GAIN_B2_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("IIR1 INP3 Volume", LPASS_CDC_IIR1_GAIN_B3_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("IIR1 INP4 Volume", LPASS_CDC_IIR1_GAIN_B4_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("IIR2 INP1 Volume", LPASS_CDC_IIR2_GAIN_B1_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("IIR2 INP2 Volume", LPASS_CDC_IIR2_GAIN_B2_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("IIR2 INP3 Volume", LPASS_CDC_IIR2_GAIN_B3_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("IIR2 INP4 Volume", LPASS_CDC_IIR2_GAIN_B4_CTL, +- 0, -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", LPASS_CDC_IIR1_GAIN_B1_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", LPASS_CDC_IIR1_GAIN_B2_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("IIR1 INP3 Volume", LPASS_CDC_IIR1_GAIN_B3_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", LPASS_CDC_IIR1_GAIN_B4_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("IIR2 INP1 Volume", LPASS_CDC_IIR2_GAIN_B1_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("IIR2 INP2 Volume", LPASS_CDC_IIR2_GAIN_B2_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("IIR2 INP3 Volume", LPASS_CDC_IIR2_GAIN_B3_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("IIR2 INP4 Volume", LPASS_CDC_IIR2_GAIN_B4_CTL, ++ -84, 40, digital_gain), + + }; + +diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c +index 6d3d170144a0a..c190628e29056 100644 +--- a/sound/soc/codecs/mt6359-accdet.c ++++ b/sound/soc/codecs/mt6359-accdet.c +@@ -675,6 +675,7 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv) + sizeof(struct three_key_threshold)); + } + ++ of_node_put(node); + dev_warn(priv->dev, "accdet caps=%x\n", priv->caps); + + return 0; +diff --git a/sound/soc/codecs/mt6359.c b/sound/soc/codecs/mt6359.c +index 2d6a4a29b8507..cf1febe54bcd9 100644 +--- a/sound/soc/codecs/mt6359.c ++++ b/sound/soc/codecs/mt6359.c +@@ -2780,6 +2780,7 @@ static int mt6359_parse_dt(struct mt6359_priv *priv) + + ret = of_property_read_u32(np, "mediatek,mic-type-2", + &priv->mux_select[MUX_MIC_TYPE_2]); ++ of_node_put(np); + if (ret) { + dev_info(priv->dev, + "%s() failed to read mic-type-2, use default (%d)\n", +diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c +index bc5d68c53e5ab..3a13afbfb74b7 100644 +--- a/sound/soc/codecs/wcd9335.c ++++ b/sound/soc/codecs/wcd9335.c +@@ -2252,51 +2252,42 @@ static int wcd9335_rx_hph_mode_put(struct snd_kcontrol *kc, + + static const struct snd_kcontrol_new wcd9335_snd_controls[] = { + /* -84dB min - 40dB max */ +- SOC_SINGLE_SX_TLV("RX0 Digital Volume", WCD9335_CDC_RX0_RX_VOL_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("RX1 Digital Volume", WCD9335_CDC_RX1_RX_VOL_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("RX2 Digital Volume", WCD9335_CDC_RX2_RX_VOL_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("RX3 Digital Volume", WCD9335_CDC_RX3_RX_VOL_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("RX4 Digital Volume", WCD9335_CDC_RX4_RX_VOL_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("RX5 Digital Volume", WCD9335_CDC_RX5_RX_VOL_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("RX6 Digital Volume", WCD9335_CDC_RX6_RX_VOL_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("RX7 Digital Volume", WCD9335_CDC_RX7_RX_VOL_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("RX8 Digital Volume", WCD9335_CDC_RX8_RX_VOL_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("RX0 Mix Digital Volume", +- WCD9335_CDC_RX0_RX_VOL_MIX_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("RX1 Mix Digital Volume", +- WCD9335_CDC_RX1_RX_VOL_MIX_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("RX2 Mix Digital Volume", +- WCD9335_CDC_RX2_RX_VOL_MIX_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("RX3 Mix Digital Volume", +- WCD9335_CDC_RX3_RX_VOL_MIX_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("RX4 Mix Digital Volume", +- WCD9335_CDC_RX4_RX_VOL_MIX_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("RX5 Mix Digital Volume", +- WCD9335_CDC_RX5_RX_VOL_MIX_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("RX6 Mix Digital Volume", +- WCD9335_CDC_RX6_RX_VOL_MIX_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("RX7 Mix Digital Volume", +- WCD9335_CDC_RX7_RX_VOL_MIX_CTL, +- 0, -84, 40, digital_gain), +- SOC_SINGLE_SX_TLV("RX8 Mix Digital Volume", +- WCD9335_CDC_RX8_RX_VOL_MIX_CTL, +- 0, -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("RX0 Digital Volume", WCD9335_CDC_RX0_RX_VOL_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("RX1 Digital Volume", WCD9335_CDC_RX1_RX_VOL_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("RX2 Digital Volume", WCD9335_CDC_RX2_RX_VOL_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("RX3 Digital Volume", WCD9335_CDC_RX3_RX_VOL_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("RX4 Digital Volume", WCD9335_CDC_RX4_RX_VOL_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("RX5 Digital Volume", WCD9335_CDC_RX5_RX_VOL_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("RX6 Digital Volume", WCD9335_CDC_RX6_RX_VOL_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("RX7 Digital Volume", WCD9335_CDC_RX7_RX_VOL_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("RX8 Digital Volume", WCD9335_CDC_RX8_RX_VOL_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("RX0 Mix Digital Volume", WCD9335_CDC_RX0_RX_VOL_MIX_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("RX1 Mix Digital Volume", WCD9335_CDC_RX1_RX_VOL_MIX_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("RX2 Mix Digital Volume", WCD9335_CDC_RX2_RX_VOL_MIX_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("RX3 Mix Digital Volume", WCD9335_CDC_RX3_RX_VOL_MIX_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("RX4 Mix Digital Volume", WCD9335_CDC_RX4_RX_VOL_MIX_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("RX5 Mix Digital Volume", WCD9335_CDC_RX5_RX_VOL_MIX_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("RX6 Mix Digital Volume", WCD9335_CDC_RX6_RX_VOL_MIX_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("RX7 Mix Digital Volume", WCD9335_CDC_RX7_RX_VOL_MIX_CTL, ++ -84, 40, digital_gain), ++ SOC_SINGLE_S8_TLV("RX8 Mix Digital Volume", WCD9335_CDC_RX8_RX_VOL_MIX_CTL, ++ -84, 40, digital_gain), + SOC_ENUM("RX INT0_1 HPF cut off", cf_int0_1_enum), + SOC_ENUM("RX INT0_2 HPF cut off", cf_int0_2_enum), + SOC_ENUM("RX INT1_1 HPF cut off", cf_int1_1_enum), +diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c +index 95286c839b57f..c72a156737e61 100644 +--- a/sound/soc/fsl/fsl-asoc-card.c ++++ b/sound/soc/fsl/fsl-asoc-card.c +@@ -540,6 +540,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) + struct device *codec_dev = NULL; + const char *codec_dai_name; + const char *codec_dev_name; ++ u32 asrc_fmt = 0; + u32 width; + int ret; + +@@ -817,8 +818,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) + goto asrc_fail; + } + +- ret = of_property_read_u32(asrc_np, "fsl,asrc-format", +- &priv->asrc_format); ++ ret = of_property_read_u32(asrc_np, "fsl,asrc-format", &asrc_fmt); ++ priv->asrc_format = (__force snd_pcm_format_t)asrc_fmt; + if (ret) { + /* Fallback to old binding; translate to asrc_format */ + ret = of_property_read_u32(asrc_np, "fsl,asrc-width", +diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c +index d7d1536a4f377..44dcbf49456cb 100644 +--- a/sound/soc/fsl/fsl_asrc.c ++++ b/sound/soc/fsl/fsl_asrc.c +@@ -1066,6 +1066,7 @@ static int fsl_asrc_probe(struct platform_device *pdev) + struct resource *res; + void __iomem *regs; + int irq, ret, i; ++ u32 asrc_fmt = 0; + u32 map_idx; + char tmp[16]; + u32 width; +@@ -1174,7 +1175,8 @@ static int fsl_asrc_probe(struct platform_device *pdev) + return ret; + } + +- ret = of_property_read_u32(np, "fsl,asrc-format", &asrc->asrc_format); ++ ret = of_property_read_u32(np, "fsl,asrc-format", &asrc_fmt); ++ asrc->asrc_format = (__force snd_pcm_format_t)asrc_fmt; + if (ret) { + ret = of_property_read_u32(np, "fsl,asrc-width", &width); + if (ret) { +@@ -1197,7 +1199,7 @@ static int fsl_asrc_probe(struct platform_device *pdev) + } + } + +- if (!(FSL_ASRC_FORMATS & (1ULL << asrc->asrc_format))) { ++ if (!(FSL_ASRC_FORMATS & pcm_format_to_bits(asrc->asrc_format))) { + dev_warn(&pdev->dev, "unsupported width, use default S24_LE\n"); + asrc->asrc_format = SNDRV_PCM_FORMAT_S24_LE; + } +diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c +index be14f84796cb4..cf0e10d17dbe3 100644 +--- a/sound/soc/fsl/fsl_easrc.c ++++ b/sound/soc/fsl/fsl_easrc.c +@@ -476,7 +476,8 @@ static int fsl_easrc_prefilter_config(struct fsl_asrc *easrc, + struct fsl_asrc_pair *ctx; + struct device *dev; + u32 inrate, outrate, offset = 0; +- u32 in_s_rate, out_s_rate, in_s_fmt, out_s_fmt; ++ u32 in_s_rate, out_s_rate; ++ snd_pcm_format_t in_s_fmt, out_s_fmt; + int ret, i; + + if (!easrc) +@@ -1873,6 +1874,7 @@ static int fsl_easrc_probe(struct platform_device *pdev) + struct resource *res; + struct device_node *np; + void __iomem *regs; ++ u32 asrc_fmt = 0; + int ret, irq; + + easrc = devm_kzalloc(dev, sizeof(*easrc), GFP_KERNEL); +@@ -1933,13 +1935,14 @@ static int fsl_easrc_probe(struct platform_device *pdev) + return ret; + } + +- ret = of_property_read_u32(np, "fsl,asrc-format", &easrc->asrc_format); ++ ret = of_property_read_u32(np, "fsl,asrc-format", &asrc_fmt); ++ easrc->asrc_format = (__force snd_pcm_format_t)asrc_fmt; + if (ret) { + dev_err(dev, "failed to asrc format\n"); + return ret; + } + +- if (!(FSL_EASRC_FORMATS & (1ULL << easrc->asrc_format))) { ++ if (!(FSL_EASRC_FORMATS & (pcm_format_to_bits(easrc->asrc_format)))) { + dev_warn(dev, "unsupported format, switching to S24_LE\n"); + easrc->asrc_format = SNDRV_PCM_FORMAT_S24_LE; + } +diff --git a/sound/soc/fsl/fsl_easrc.h b/sound/soc/fsl/fsl_easrc.h +index 30620d56252cc..5b8469757c122 100644 +--- a/sound/soc/fsl/fsl_easrc.h ++++ b/sound/soc/fsl/fsl_easrc.h +@@ -569,7 +569,7 @@ struct fsl_easrc_io_params { + unsigned int access_len; + unsigned int fifo_wtmk; + unsigned int sample_rate; +- unsigned int sample_format; ++ snd_pcm_format_t sample_format; + unsigned int norm_rate; + }; + +diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c +index dfa05d40b2764..a8e5e0f57faf9 100644 +--- a/sound/soc/fsl/imx-audmux.c ++++ b/sound/soc/fsl/imx-audmux.c +@@ -298,7 +298,7 @@ static int imx_audmux_probe(struct platform_device *pdev) + audmux_clk = NULL; + } + +- audmux_type = (enum imx_audmux_type)of_device_get_match_data(&pdev->dev); ++ audmux_type = (uintptr_t)of_device_get_match_data(&pdev->dev); + + switch (audmux_type) { + case IMX31_AUDMUX: +diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c +index 55bc1bb0dbbd3..593d69b965238 100644 +--- a/sound/soc/fsl/imx-card.c ++++ b/sound/soc/fsl/imx-card.c +@@ -17,6 +17,9 @@ + + #include "fsl_sai.h" + ++#define IMX_CARD_MCLK_22P5792MHZ 22579200 ++#define IMX_CARD_MCLK_24P576MHZ 24576000 ++ + enum codec_type { + CODEC_DUMMY = 0, + CODEC_AK5558 = 1, +@@ -115,7 +118,7 @@ struct imx_card_data { + struct snd_soc_card card; + int num_dapm_routes; + u32 asrc_rate; +- u32 asrc_format; ++ snd_pcm_format_t asrc_format; + }; + + static struct imx_akcodec_fs_mul ak4458_fs_mul[] = { +@@ -353,9 +356,14 @@ static int imx_aif_hw_params(struct snd_pcm_substream *substream, + mclk_freq = akcodec_get_mclk_rate(substream, params, slots, slot_width); + else + mclk_freq = params_rate(params) * slots * slot_width; +- /* Use the maximum freq from DSD512 (512*44100 = 22579200) */ +- if (format_is_dsd(params)) +- mclk_freq = 22579200; ++ ++ if (format_is_dsd(params)) { ++ /* Use the maximum freq from DSD512 (512*44100 = 22579200) */ ++ if (!(params_rate(params) % 11025)) ++ mclk_freq = IMX_CARD_MCLK_22P5792MHZ; ++ else ++ mclk_freq = IMX_CARD_MCLK_24P576MHZ; ++ } + + ret = snd_soc_dai_set_sysclk(cpu_dai, link_data->cpu_sysclk_id, mclk_freq, + SND_SOC_CLOCK_OUT); +@@ -466,7 +474,7 @@ static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + + mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + snd_mask_none(mask); +- snd_mask_set(mask, data->asrc_format); ++ snd_mask_set(mask, (__force unsigned int)data->asrc_format); + + return 0; + } +@@ -485,6 +493,7 @@ static int imx_card_parse_of(struct imx_card_data *data) + struct dai_link_data *link_data; + struct of_phandle_args args; + int ret, num_links; ++ u32 asrc_fmt = 0; + u32 width; + + ret = snd_soc_of_parse_card_name(card, "model"); +@@ -631,7 +640,8 @@ static int imx_card_parse_of(struct imx_card_data *data) + goto err; + } + +- ret = of_property_read_u32(args.np, "fsl,asrc-format", &data->asrc_format); ++ ret = of_property_read_u32(args.np, "fsl,asrc-format", &asrc_fmt); ++ data->asrc_format = (__force snd_pcm_format_t)asrc_fmt; + if (ret) { + /* Fallback to old binding; translate to asrc_format */ + ret = of_property_read_u32(args.np, "fsl,asrc-width", &width); +diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c +index 546f6fd0609e1..28cbcdb56857f 100644 +--- a/sound/soc/generic/audio-graph-card.c ++++ b/sound/soc/generic/audio-graph-card.c +@@ -158,8 +158,10 @@ static int asoc_simple_parse_dai(struct device_node *ep, + * if he unbinded CPU or Codec. + */ + ret = snd_soc_get_dai_name(&args, &dlc->dai_name); +- if (ret < 0) ++ if (ret < 0) { ++ of_node_put(node); + return ret; ++ } + + dlc->of_node = node; + +diff --git a/sound/soc/mediatek/mt6797/mt6797-mt6351.c b/sound/soc/mediatek/mt6797/mt6797-mt6351.c +index 496f32bcfb5e3..d2f6213a6bfcc 100644 +--- a/sound/soc/mediatek/mt6797/mt6797-mt6351.c ++++ b/sound/soc/mediatek/mt6797/mt6797-mt6351.c +@@ -217,7 +217,8 @@ static int mt6797_mt6351_dev_probe(struct platform_device *pdev) + if (!codec_node) { + dev_err(&pdev->dev, + "Property 'audio-codec' missing or invalid\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto put_platform_node; + } + for_each_card_prelinks(card, i, dai_link) { + if (dai_link->codecs->name) +@@ -230,6 +231,9 @@ static int mt6797_mt6351_dev_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", + __func__, ret); + ++ of_node_put(codec_node); ++put_platform_node: ++ of_node_put(platform_node); + return ret; + } + +diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c +index c8e4e85e10575..94a9bbf144d15 100644 +--- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c ++++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c +@@ -256,14 +256,16 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev) + if (!mt8173_rt5650_rt5676_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 put_node; + } + mt8173_rt5650_rt5676_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node = + of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 1); + if (!mt8173_rt5650_rt5676_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 put_node; + } + mt8173_rt5650_rt5676_codec_conf[0].dlc.of_node = + mt8173_rt5650_rt5676_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node; +@@ -276,7 +278,8 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev) + if (!mt8173_rt5650_rt5676_dais[DAI_LINK_HDMI_I2S].codecs->of_node) { + dev_err(&pdev->dev, + "Property 'audio-codec' missing or invalid\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto put_node; + } + + card->dev = &pdev->dev; +@@ -286,6 +289,7 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", + __func__, ret); + ++put_node: + of_node_put(platform_node); + return ret; + } +diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650.c b/sound/soc/mediatek/mt8173/mt8173-rt5650.c +index e168d31f44459..1de9dab218c64 100644 +--- a/sound/soc/mediatek/mt8173/mt8173-rt5650.c ++++ b/sound/soc/mediatek/mt8173/mt8173-rt5650.c +@@ -280,7 +280,8 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev) + if (!mt8173_rt5650_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 put_platform_node; + } + mt8173_rt5650_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node = + mt8173_rt5650_dais[DAI_LINK_CODEC_I2S].codecs[0].of_node; +@@ -293,7 +294,7 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev) + dev_err(&pdev->dev, + "%s codec_capture_dai name fail %d\n", + __func__, ret); +- return ret; ++ goto put_platform_node; + } + mt8173_rt5650_dais[DAI_LINK_CODEC_I2S].codecs[1].dai_name = + codec_capture_dai; +@@ -315,7 +316,8 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev) + if (!mt8173_rt5650_dais[DAI_LINK_HDMI_I2S].codecs->of_node) { + dev_err(&pdev->dev, + "Property 'audio-codec' missing or invalid\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto put_platform_node; + } + card->dev = &pdev->dev; + +@@ -324,6 +326,7 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", + __func__, ret); + ++put_platform_node: + of_node_put(platform_node); + return ret; + } +diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c +index 3bd9eb3cc688b..5e89d280e3550 100644 +--- a/sound/soc/qcom/lpass-cpu.c ++++ b/sound/soc/qcom/lpass-cpu.c +@@ -880,6 +880,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) + dsp_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,adsp", 0); + if (dsp_of_node) { + dev_err(dev, "DSP exists and holds audio resources\n"); ++ of_node_put(dsp_of_node); + return -EBUSY; + } + +diff --git a/sound/soc/qcom/qdsp6/q6adm.c b/sound/soc/qcom/qdsp6/q6adm.c +index 3d831b635524f..4ae97afe90624 100644 +--- a/sound/soc/qcom/qdsp6/q6adm.c ++++ b/sound/soc/qcom/qdsp6/q6adm.c +@@ -217,7 +217,7 @@ static struct q6copp *q6adm_alloc_copp(struct q6adm *adm, int port_idx) + idx = find_first_zero_bit(&adm->copp_bitmap[port_idx], + MAX_COPPS_PER_PORT); + +- if (idx > MAX_COPPS_PER_PORT) ++ if (idx >= MAX_COPPS_PER_PORT) + return ERR_PTR(-EBUSY); + + c = kzalloc(sizeof(*c), GFP_ATOMIC); +diff --git a/sound/soc/samsung/aries_wm8994.c b/sound/soc/samsung/aries_wm8994.c +index 83acbe57b2489..a0825da9fff97 100644 +--- a/sound/soc/samsung/aries_wm8994.c ++++ b/sound/soc/samsung/aries_wm8994.c +@@ -628,8 +628,10 @@ static int aries_audio_probe(struct platform_device *pdev) + return -EINVAL; + + codec = of_get_child_by_name(dev->of_node, "codec"); +- if (!codec) +- return -EINVAL; ++ if (!codec) { ++ ret = -EINVAL; ++ goto out; ++ } + + for_each_card_prelinks(card, i, dai_link) { + dai_link->codecs->of_node = of_parse_phandle(codec, +diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c +index c994e67d1eaf0..ca086243fcfd6 100644 +--- a/sound/soc/samsung/h1940_uda1380.c ++++ b/sound/soc/samsung/h1940_uda1380.c +@@ -8,7 +8,7 @@ + // Based on version from Arnaud Patard <arnaud.patard@rtp-net.org> + + #include <linux/types.h> +-#include <linux/gpio.h> ++#include <linux/gpio/consumer.h> + #include <linux/module.h> + + #include <sound/soc.h> +diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c +index 6ea1c8cc91675..2820097b00b93 100644 +--- a/sound/soc/samsung/rx1950_uda1380.c ++++ b/sound/soc/samsung/rx1950_uda1380.c +@@ -128,7 +128,7 @@ static int rx1950_startup(struct snd_pcm_substream *substream) + &hw_rates); + } + +-struct gpio_desc *gpiod_speaker_power; ++static struct gpio_desc *gpiod_speaker_power; + + static int rx1950_spk_power(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +@@ -227,7 +227,7 @@ static int rx1950_probe(struct platform_device *pdev) + return devm_snd_soc_register_card(dev, &rx1950_asoc); + } + +-struct platform_driver rx1950_audio = { ++static struct platform_driver rx1950_audio = { + .driver = { + .name = "rx1950-audio", + .pm = &snd_soc_pm_ops, +diff --git a/sound/usb/bcd2000/bcd2000.c b/sound/usb/bcd2000/bcd2000.c +index cd4a0bc6d278f..7aec0a95c609a 100644 +--- a/sound/usb/bcd2000/bcd2000.c ++++ b/sound/usb/bcd2000/bcd2000.c +@@ -348,7 +348,8 @@ static int bcd2000_init_midi(struct bcd2000 *bcd2k) + static void bcd2000_free_usb_related_resources(struct bcd2000 *bcd2k, + struct usb_interface *interface) + { +- /* usb_kill_urb not necessary, urb is aborted automatically */ ++ usb_kill_urb(bcd2k->midi_out_urb); ++ usb_kill_urb(bcd2k->midi_in_urb); + + usb_free_urb(bcd2k->midi_out_urb); + usb_free_urb(bcd2k->midi_in_urb); +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 968d90caeefa0..168fd802d70bd 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -1843,6 +1843,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), + DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ + QUIRK_FLAG_GET_SAMPLE_RATE), ++ DEVICE_FLG(0x1397, 0x0507, /* Behringer UMC202HD */ ++ QUIRK_FLAG_PLAYBACK_FIRST | QUIRK_FLAG_GENERIC_IMPLICIT_FB), + DEVICE_FLG(0x1397, 0x0508, /* Behringer UMC204HD */ + QUIRK_FLAG_PLAYBACK_FIRST | QUIRK_FLAG_GENERIC_IMPLICIT_FB), + DEVICE_FLG(0x1397, 0x0509, /* Behringer UMC404HD */ +diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c +index 33c19590ee434..4435c09fe132f 100644 +--- a/tools/lib/bpf/gen_loader.c ++++ b/tools/lib/bpf/gen_loader.c +@@ -480,7 +480,7 @@ void bpf_gen__record_attach_target(struct bpf_gen *gen, const char *attach_name, + gen->attach_kind = kind; + ret = snprintf(gen->attach_target, sizeof(gen->attach_target), "%s%s", + prefix, attach_name); +- if (ret == sizeof(gen->attach_target)) ++ if (ret >= sizeof(gen->attach_target)) + gen->error = -ENOSPC; + } + +diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c +index 1ba2dd3523f81..050622649797c 100644 +--- a/tools/lib/bpf/libbpf.c ++++ b/tools/lib/bpf/libbpf.c +@@ -3942,7 +3942,7 @@ static int bpf_get_map_info_from_fdinfo(int fd, struct bpf_map_info *info) + int bpf_map__reuse_fd(struct bpf_map *map, int fd) + { + struct bpf_map_info info = {}; +- __u32 len = sizeof(info); ++ __u32 len = sizeof(info), name_len; + int new_fd, err; + char *new_name; + +@@ -3952,7 +3952,12 @@ int bpf_map__reuse_fd(struct bpf_map *map, int fd) + if (err) + return libbpf_err(err); + +- new_name = strdup(info.name); ++ name_len = strlen(info.name); ++ if (name_len == BPF_OBJ_NAME_LEN - 1 && strncmp(map->name, info.name, name_len) == 0) ++ new_name = strdup(map->name); ++ else ++ new_name = strdup(info.name); ++ + if (!new_name) + return libbpf_err(-errno); + +diff --git a/tools/lib/bpf/xsk.c b/tools/lib/bpf/xsk.c +index a27b3141463ad..42b8437b05350 100644 +--- a/tools/lib/bpf/xsk.c ++++ b/tools/lib/bpf/xsk.c +@@ -1164,8 +1164,6 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr, + goto out_mmap_tx; + } + +- ctx->prog_fd = -1; +- + if (!(xsk->config.libbpf_flags & XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD)) { + err = __xsk_setup_xdp_prog(xsk, NULL); + if (err) +@@ -1246,7 +1244,10 @@ void xsk_socket__delete(struct xsk_socket *xsk) + + ctx = xsk->ctx; + umem = ctx->umem; +- if (ctx->prog_fd != -1) { ++ ++ xsk_put_ctx(ctx, true); ++ ++ if (!ctx->refcount) { + xsk_delete_bpf_maps(xsk); + close(ctx->prog_fd); + if (ctx->has_bpf_link) +@@ -1265,8 +1266,6 @@ void xsk_socket__delete(struct xsk_socket *xsk) + } + } + +- xsk_put_ctx(ctx, true); +- + umem->refcount--; + /* Do not close an fd that also has an associated umem connected + * to it. +diff --git a/tools/perf/util/dsos.c b/tools/perf/util/dsos.c +index 183a81d5b2f92..2db91121bdafe 100644 +--- a/tools/perf/util/dsos.c ++++ b/tools/perf/util/dsos.c +@@ -20,8 +20,19 @@ static int __dso_id__cmp(struct dso_id *a, struct dso_id *b) + if (a->ino > b->ino) return -1; + if (a->ino < b->ino) return 1; + +- if (a->ino_generation > b->ino_generation) return -1; +- if (a->ino_generation < b->ino_generation) return 1; ++ /* ++ * Synthesized MMAP events have zero ino_generation, avoid comparing ++ * them with MMAP events with actual ino_generation. ++ * ++ * I found it harmful because the mismatch resulted in a new ++ * dso that did not have a build ID whereas the original dso did have a ++ * build ID. The build ID was essential because the object was not found ++ * otherwise. - Adrian ++ */ ++ if (a->ino_generation && b->ino_generation) { ++ if (a->ino_generation > b->ino_generation) return -1; ++ if (a->ino_generation < b->ino_generation) return 1; ++ } + + return 0; + } +diff --git a/tools/perf/util/genelf.c b/tools/perf/util/genelf.c +index aed49806a09ba..953338b9e887e 100644 +--- a/tools/perf/util/genelf.c ++++ b/tools/perf/util/genelf.c +@@ -30,7 +30,11 @@ + + #define BUILD_ID_URANDOM /* different uuid for each run */ + +-#ifdef HAVE_LIBCRYPTO ++// FIXME, remove this and fix the deprecation warnings before its removed and ++// We'll break for good here... ++#pragma GCC diagnostic ignored "-Wdeprecated-declarations" ++ ++#ifdef HAVE_LIBCRYPTO_SUPPORT + + #define BUILD_ID_MD5 + #undef BUILD_ID_SHA /* does not seem to work well when linked with Java */ +diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c +index ef6ced5c5746a..cb7b244937826 100644 +--- a/tools/perf/util/symbol-elf.c ++++ b/tools/perf/util/symbol-elf.c +@@ -1294,16 +1294,29 @@ dso__load_sym_internal(struct dso *dso, struct map *map, struct symsrc *syms_ss, + + if (elf_read_program_header(syms_ss->elf, + (u64)sym.st_value, &phdr)) { +- pr_warning("%s: failed to find program header for " ++ pr_debug4("%s: failed to find program header for " + "symbol: %s st_value: %#" PRIx64 "\n", + __func__, elf_name, (u64)sym.st_value); +- continue; ++ pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " " ++ "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", ++ __func__, (u64)sym.st_value, (u64)shdr.sh_addr, ++ (u64)shdr.sh_offset); ++ /* ++ * Fail to find program header, let's rollback ++ * to use shdr.sh_addr and shdr.sh_offset to ++ * calibrate symbol's file address, though this ++ * is not necessary for normal C ELF file, we ++ * still need to handle java JIT symbols in this ++ * case. ++ */ ++ sym.st_value -= shdr.sh_addr - shdr.sh_offset; ++ } else { ++ pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " " ++ "p_vaddr: %#" PRIx64 " p_offset: %#" PRIx64 "\n", ++ __func__, (u64)sym.st_value, (u64)phdr.p_vaddr, ++ (u64)phdr.p_offset); ++ sym.st_value -= phdr.p_vaddr - phdr.p_offset; + } +- pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " " +- "p_vaddr: %#" PRIx64 " p_offset: %#" PRIx64 "\n", +- __func__, (u64)sym.st_value, (u64)phdr.p_vaddr, +- (u64)phdr.p_offset); +- sym.st_value -= phdr.p_vaddr - phdr.p_offset; + } + + demangled = demangle_sym(dso, kmodule, elf_name); +diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c +index ed563bdd88f39..b752ce47ead3c 100644 +--- a/tools/testing/nvdimm/test/iomap.c ++++ b/tools/testing/nvdimm/test/iomap.c +@@ -100,25 +100,17 @@ static void nfit_test_kill(void *_pgmap) + { + struct dev_pagemap *pgmap = _pgmap; + +- WARN_ON(!pgmap || !pgmap->ref); +- +- if (pgmap->ops && pgmap->ops->kill) +- pgmap->ops->kill(pgmap); +- else +- percpu_ref_kill(pgmap->ref); +- +- if (pgmap->ops && pgmap->ops->cleanup) { +- pgmap->ops->cleanup(pgmap); +- } else { +- wait_for_completion(&pgmap->done); +- percpu_ref_exit(pgmap->ref); +- } ++ WARN_ON(!pgmap); ++ ++ percpu_ref_kill(&pgmap->ref); ++ ++ wait_for_completion(&pgmap->done); ++ percpu_ref_exit(&pgmap->ref); + } + + static void dev_pagemap_percpu_release(struct percpu_ref *ref) + { +- struct dev_pagemap *pgmap = +- container_of(ref, struct dev_pagemap, internal_ref); ++ struct dev_pagemap *pgmap = container_of(ref, struct dev_pagemap, ref); + + complete(&pgmap->done); + } +@@ -132,22 +124,11 @@ void *__wrap_devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap) + if (!nfit_res) + return devm_memremap_pages(dev, pgmap); + +- if (!pgmap->ref) { +- if (pgmap->ops && (pgmap->ops->kill || pgmap->ops->cleanup)) +- return ERR_PTR(-EINVAL); +- +- init_completion(&pgmap->done); +- error = percpu_ref_init(&pgmap->internal_ref, +- dev_pagemap_percpu_release, 0, GFP_KERNEL); +- if (error) +- return ERR_PTR(error); +- pgmap->ref = &pgmap->internal_ref; +- } else { +- if (!pgmap->ops || !pgmap->ops->kill || !pgmap->ops->cleanup) { +- WARN(1, "Missing reference count teardown definition\n"); +- return ERR_PTR(-EINVAL); +- } +- } ++ init_completion(&pgmap->done); ++ error = percpu_ref_init(&pgmap->ref, dev_pagemap_percpu_release, 0, ++ GFP_KERNEL); ++ if (error) ++ return ERR_PTR(error); + + error = devm_add_action_or_reset(dev, nfit_test_kill, pgmap); + if (error) +diff --git a/tools/testing/selftests/bpf/prog_tests/btf.c b/tools/testing/selftests/bpf/prog_tests/btf.c +index 649f87382c8d8..50afa75bd45b1 100644 +--- a/tools/testing/selftests/bpf/prog_tests/btf.c ++++ b/tools/testing/selftests/bpf/prog_tests/btf.c +@@ -4913,7 +4913,7 @@ static void do_test_pprint(int test_num) + ret = snprintf(pin_path, sizeof(pin_path), "%s/%s", + "/sys/fs/bpf", test->map_name); + +- if (CHECK(ret == sizeof(pin_path), "pin_path %s/%s is too long", ++ if (CHECK(ret >= sizeof(pin_path), "pin_path %s/%s is too long", + "/sys/fs/bpf", test->map_name)) { + err = -1; + goto done; +diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c +index 46057079d8bba..4f1449fa9592e 100644 +--- a/tools/testing/selftests/kvm/lib/x86_64/processor.c ++++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c +@@ -1326,7 +1326,7 @@ uint64_t kvm_hypercall(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2, + + asm volatile("vmcall" + : "=a"(r) +- : "b"(a0), "c"(a1), "d"(a2), "S"(a3)); ++ : "a"(nr), "b"(a0), "c"(a1), "d"(a2), "S"(a3)); + return r; + } + +diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c +index 34ebd1fe5eed2..ac340a9c09187 100644 +--- a/tools/testing/selftests/seccomp/seccomp_bpf.c ++++ b/tools/testing/selftests/seccomp/seccomp_bpf.c +@@ -802,7 +802,7 @@ void kill_thread_or_group(struct __test_metadata *_metadata, + .len = (unsigned short)ARRAY_SIZE(filter_thread), + .filter = filter_thread, + }; +- int kill = kill_how == KILL_PROCESS ? SECCOMP_RET_KILL_PROCESS : 0xAAAAAAAAA; ++ int kill = kill_how == KILL_PROCESS ? SECCOMP_RET_KILL_PROCESS : 0xAAAAAAAA; + struct sock_filter filter_process[] = { + BPF_STMT(BPF_LD|BPF_W|BPF_ABS, + offsetof(struct seccomp_data, nr)), +diff --git a/tools/testing/selftests/timers/clocksource-switch.c b/tools/testing/selftests/timers/clocksource-switch.c +index ef8eb3604595e..b57f0a9be4902 100644 +--- a/tools/testing/selftests/timers/clocksource-switch.c ++++ b/tools/testing/selftests/timers/clocksource-switch.c +@@ -110,10 +110,10 @@ int run_tests(int secs) + + sprintf(buf, "./inconsistency-check -t %i", secs); + ret = system(buf); +- if (ret) +- return ret; ++ if (WIFEXITED(ret) && WEXITSTATUS(ret)) ++ return WEXITSTATUS(ret); + ret = system("./nanosleep"); +- return ret; ++ return WIFEXITED(ret) ? WEXITSTATUS(ret) : 0; + } + + +diff --git a/tools/testing/selftests/timers/valid-adjtimex.c b/tools/testing/selftests/timers/valid-adjtimex.c +index 5397de708d3c2..48b9a803235a8 100644 +--- a/tools/testing/selftests/timers/valid-adjtimex.c ++++ b/tools/testing/selftests/timers/valid-adjtimex.c +@@ -40,7 +40,7 @@ + #define ADJ_SETOFFSET 0x0100 + + #include <sys/syscall.h> +-static int clock_adjtime(clockid_t id, struct timex *tx) ++int clock_adjtime(clockid_t id, struct timex *tx) + { + return syscall(__NR_clock_adjtime, id, tx); + } +diff --git a/tools/thermal/tmon/sysfs.c b/tools/thermal/tmon/sysfs.c +index b00b1bfd9d8e7..cb1108bc92498 100644 +--- a/tools/thermal/tmon/sysfs.c ++++ b/tools/thermal/tmon/sysfs.c +@@ -13,6 +13,7 @@ + #include <stdint.h> + #include <dirent.h> + #include <libintl.h> ++#include <limits.h> + #include <ctype.h> + #include <time.h> + #include <syslog.h> +@@ -33,9 +34,9 @@ int sysfs_set_ulong(char *path, char *filename, unsigned long val) + { + FILE *fd; + int ret = -1; +- char filepath[256]; ++ char filepath[PATH_MAX + 2]; /* NUL and '/' */ + +- snprintf(filepath, 256, "%s/%s", path, filename); ++ snprintf(filepath, sizeof(filepath), "%s/%s", path, filename); + + fd = fopen(filepath, "w"); + if (!fd) { +@@ -57,9 +58,9 @@ static int sysfs_get_ulong(char *path, char *filename, unsigned long *p_ulong) + { + FILE *fd; + int ret = -1; +- char filepath[256]; ++ char filepath[PATH_MAX + 2]; /* NUL and '/' */ + +- snprintf(filepath, 256, "%s/%s", path, filename); ++ snprintf(filepath, sizeof(filepath), "%s/%s", path, filename); + + fd = fopen(filepath, "r"); + if (!fd) { +@@ -76,9 +77,9 @@ static int sysfs_get_string(char *path, char *filename, char *str) + { + FILE *fd; + int ret = -1; +- char filepath[256]; ++ char filepath[PATH_MAX + 2]; /* NUL and '/' */ + +- snprintf(filepath, 256, "%s/%s", path, filename); ++ snprintf(filepath, sizeof(filepath), "%s/%s", path, filename); + + fd = fopen(filepath, "r"); + if (!fd) { +@@ -199,8 +200,8 @@ static int find_tzone_cdev(struct dirent *nl, char *tz_name, + { + unsigned long trip_instance = 0; + char cdev_name_linked[256]; +- char cdev_name[256]; +- char cdev_trip_name[256]; ++ char cdev_name[PATH_MAX]; ++ char cdev_trip_name[PATH_MAX]; + int cdev_id; + + if (nl->d_type == DT_LNK) { +@@ -213,7 +214,8 @@ static int find_tzone_cdev(struct dirent *nl, char *tz_name, + return -EINVAL; + } + /* find the link to real cooling device record binding */ +- snprintf(cdev_name, 256, "%s/%s", tz_name, nl->d_name); ++ snprintf(cdev_name, sizeof(cdev_name) - 2, "%s/%s", ++ tz_name, nl->d_name); + memset(cdev_name_linked, 0, sizeof(cdev_name_linked)); + if (readlink(cdev_name, cdev_name_linked, + sizeof(cdev_name_linked) - 1) != -1) { +@@ -226,8 +228,8 @@ static int find_tzone_cdev(struct dirent *nl, char *tz_name, + /* find the trip point in which the cdev is binded to + * in this tzone + */ +- snprintf(cdev_trip_name, 256, "%s%s", nl->d_name, +- "_trip_point"); ++ snprintf(cdev_trip_name, sizeof(cdev_trip_name) - 1, ++ "%s%s", nl->d_name, "_trip_point"); + sysfs_get_ulong(tz_name, cdev_trip_name, + &trip_instance); + /* validate trip point range, e.g. trip could return -1 +diff --git a/tools/thermal/tmon/tmon.h b/tools/thermal/tmon/tmon.h +index c9066ec104ddd..44d16d778f044 100644 +--- a/tools/thermal/tmon/tmon.h ++++ b/tools/thermal/tmon/tmon.h +@@ -27,6 +27,9 @@ + #define NR_LINES_TZDATA 1 + #define TMON_LOG_FILE "/var/tmp/tmon.log" + ++#include <sys/time.h> ++#include <pthread.h> ++ + extern unsigned long ticktime; + extern double time_elapsed; + extern unsigned long target_temp_user; +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index 0816b8018cde2..251b4143f505b 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -2762,16 +2762,28 @@ void kvm_release_pfn_dirty(kvm_pfn_t pfn) + } + EXPORT_SYMBOL_GPL(kvm_release_pfn_dirty); + ++static bool kvm_is_ad_tracked_pfn(kvm_pfn_t pfn) ++{ ++ if (!pfn_valid(pfn)) ++ return false; ++ ++ /* ++ * Per page-flags.h, pages tagged PG_reserved "should in general not be ++ * touched (e.g. set dirty) except by its owner". ++ */ ++ return !PageReserved(pfn_to_page(pfn)); ++} ++ + void kvm_set_pfn_dirty(kvm_pfn_t pfn) + { +- if (!kvm_is_reserved_pfn(pfn) && !kvm_is_zone_device_pfn(pfn)) ++ if (kvm_is_ad_tracked_pfn(pfn)) + SetPageDirty(pfn_to_page(pfn)); + } + EXPORT_SYMBOL_GPL(kvm_set_pfn_dirty); + + void kvm_set_pfn_accessed(kvm_pfn_t pfn) + { +- if (!kvm_is_reserved_pfn(pfn) && !kvm_is_zone_device_pfn(pfn)) ++ if (kvm_is_ad_tracked_pfn(pfn)) + mark_page_accessed(pfn_to_page(pfn)); + } + EXPORT_SYMBOL_GPL(kvm_set_pfn_accessed); |