summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pagano <mpagano@gentoo.org>2022-08-17 10:32:06 -0400
committerMike Pagano <mpagano@gentoo.org>2022-08-17 10:32:06 -0400
commit86706d28e7cd7d5f8ea3bef5964fe031c1c03df0 (patch)
tree2b3bcccb84650d244ff63eb17930868cc0ea42b2
parentLinux patch 5.15.60 (diff)
downloadlinux-patches-86706d28.tar.gz
linux-patches-86706d28.tar.bz2
linux-patches-86706d28.zip
Linux patch 5.15.615.15-65
Signed-off-by: Mike Pagano <mpagano@gentoo.org>
-rw-r--r--0000_README4
-rw-r--r--1060_linux-5.15.61.patch42556
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 = <&reg_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 = <&reg_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(&note, 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), &notn_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(&lt9611uxc->work);
+ lt9611uxc_audio_exit(lt9611uxc);
+ drm_bridge_remove(&lt9611uxc->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, &param);
+@@ -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 = &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);